Git.pm: Add support for subdirectories inside of working copies
This patch adds support for subdirectories inside of working copies;
you can specify them in the constructor either as the Directory
option (it will just get autodetected using rev-parse) or explicitly
using the WorkingSubdir option. This makes Git->repository() do the
exact same path setup and repository lookup as the Git porcelain
does.
This patch also introduces repo_path(), wc_path() and wc_subdir()
accessor methods and wc_chdir() mutator.
Signed-off-by: Petr Baudis <pasky@suse.cz>
Signed-off-by: Junio C Hamano <junkio@cox.net>
@ -69,20 +69,18 @@ means getting an instance of the Git object using the repository() constructor.
@@ -69,20 +69,18 @@ means getting an instance of the Git object using the repository() constructor.
called as methods of the object are then executed in the context of the
repository.
TODO: In the future, we might also do
Part of the "repository state" is also information about path to the attached
working copy (unless you work with a bare repository). You can also navigate
inside of the working copy using the C<wc_chdir()> method. (Note that
the repository object is self-contained and will not change working directory
of your process.)
my $subdir = $repo->subdir('Documentation');
# Gets called in the subdirectory context:
$subdir->command('status');
TODO: In the future, we might also do
my $remoterepo = $repo->remote_repository (Name => 'cogito', Branch => 'master');
use Carp qw(carp croak); # but croak is bad - throw instead
use Error qw(:try);
use Cwd qw(abs_path);
require XSLoader;
XSLoader::load('Git', $VERSION);
@ -119,12 +118,17 @@ B<Repository> - Path to the Git repository.
@@ -119,12 +118,17 @@ B<Repository> - Path to the Git repository.
B<WorkingCopy> - Path to the associated working copy; not strictly required
as many commands will happily crunch on a bare repository.
B<Directory> - Path to the Git working directory in its usual setup. This
is just for convenient setting of both C<Repository> and C<WorkingCopy>
at once: If the directory as a C<.git> subdirectory, C<Repository> is pointed
to the subdirectory and the directory is assumed to be the working copy.
If the directory does not have the subdirectory, C<WorkingCopy> is left
undefined and C<Repository> is pointed to the directory itself.
B<WorkingSubdir> - Subdirectory in the working copy to work inside.
Just left undefined if you do not want to limit the scope of operations.
B<Directory> - Path to the Git working directory in its usual setup.
The C<.git> directory is searched in the directory and all the parent
directories; if found, C<WorkingCopy> is set to the directory containing
it and C<Repository> to the C<.git> directory itself. If no C<.git>
directory was found, the C<Directory> is assumed to be a bare repository,
C<Repository> is set to point at it and C<WorkingCopy> is left undefined.
If the C<$GIT_DIR> environment variable is set, things behave as expected
as well.
You should not use both C<Directory> and either of C<Repository> and
C<WorkingCopy> - the results of that are undefined.
@ -134,7 +138,10 @@ to the constructor; it is equivalent to setting only the C<Directory> option
@@ -134,7 +138,10 @@ to the constructor; it is equivalent to setting only the C<Directory> option
field.
Calling the constructor with no options whatsoever is equivalent to
calling it with C<< Directory => '.' >>.
calling it with C<< Directory => '.' >>. In general, if you are building
a standard porcelain command, simply doing C<< Git->repository() >> should
do the right thing and setup the object to reflect exactly where the user
is right now.
=cut
@ -152,18 +159,59 @@ sub repository {
@@ -152,18 +159,59 @@ sub repository {
} else {
%opts = @args;
}
}
if (not defined $opts{Repository} and not defined $opts{WorkingCopy}) {
$opts{Directory} ||= '.';
}
if ($opts{Directory}) {
-d $opts{Directory} or throw Error::Simple("Directory not found: $!");
if (-d $opts{Directory}."/.git") {
# TODO: Might make this more clever
$opts{WorkingCopy} = $opts{Directory};
$opts{Repository} = $opts{Directory}."/.git";
my $search = Git->repository(WorkingCopy => $opts{Directory});