5c5ae1246b717ad1bf6217254175111d4cc8b45a
   1=head1 NAME
   2
   3Git - Perl interface to the Git version control system
   4
   5=cut
   6
   7
   8package Git;
   9
  10use strict;
  11
  12
  13BEGIN {
  14
  15our ($VERSION, @ISA, @EXPORT, @EXPORT_OK);
  16
  17# Totally unstable API.
  18$VERSION = '0.01';
  19
  20
  21=head1 SYNOPSIS
  22
  23  use Git;
  24
  25  my $version = Git::command_oneline('version');
  26
  27  Git::command_noisy('update-server-info');
  28
  29  my $repo = Git->repository (Directory => '/srv/git/cogito.git');
  30
  31
  32  my @revs = $repo->command('rev-list', '--since=last monday', '--all');
  33
  34  my $fh = $repo->command_pipe('rev-list', '--since=last monday', '--all');
  35  my $lastrev = <$fh>; chomp $lastrev;
  36  close $fh; # You may want to test rev-list exit status here
  37
  38  my $lastrev = $repo->command_oneline('rev-list', '--all');
  39
  40=cut
  41
  42
  43require Exporter;
  44
  45@ISA = qw(Exporter);
  46
  47@EXPORT = qw();
  48
  49# Methods which can be called as standalone functions as well:
  50@EXPORT_OK = qw(command command_oneline command_pipe command_noisy
  51                exec_path hash_object);
  52
  53
  54=head1 DESCRIPTION
  55
  56This module provides Perl scripts easy way to interface the Git version control
  57system. The modules have an easy and well-tested way to call arbitrary Git
  58commands; in the future, the interface will also provide specialized methods
  59for doing easily operations which are not totally trivial to do over
  60the generic command interface.
  61
  62While some commands can be executed outside of any context (e.g. 'version'
  63or 'init-db'), most operations require a repository context, which in practice
  64means getting an instance of the Git object using the repository() constructor.
  65(In the future, we will also get a new_repository() constructor.) All commands
  66called as methods of the object are then executed in the context of the
  67repository.
  68
  69TODO: In the future, we might also do
  70
  71        my $subdir = $repo->subdir('Documentation');
  72        # Gets called in the subdirectory context:
  73        $subdir->command('status');
  74
  75        my $remoterepo = $repo->remote_repository (Name => 'cogito', Branch => 'master');
  76        $remoterepo ||= Git->remote_repository ('http://git.or.cz/cogito.git/');
  77        my @refs = $remoterepo->refs();
  78
  79So far, all functions just die if anything goes wrong. If you don't want that,
  80make appropriate provisions to catch the possible deaths. Better error recovery
  81mechanisms will be provided in the future.
  82
  83Currently, the module merely wraps calls to external Git tools. In the future,
  84it will provide a much faster way to interact with Git by linking directly
  85to libgit. This should be completely opaque to the user, though (performance
  86increate nonwithstanding).
  87
  88=cut
  89
  90
  91use Carp qw(carp croak);
  92
  93require XSLoader;
  94XSLoader::load('Git', $VERSION);
  95
  96}
  97
  98
  99=head1 CONSTRUCTORS
 100
 101=over 4
 102
 103=item repository ( OPTIONS )
 104
 105=item repository ( DIRECTORY )
 106
 107=item repository ()
 108
 109Construct a new repository object.
 110C<OPTIONS> are passed in a hash like fashion, using key and value pairs.
 111Possible options are:
 112
 113B<Repository> - Path to the Git repository.
 114
 115B<WorkingCopy> - Path to the associated working copy; not strictly required
 116as many commands will happily crunch on a bare repository.
 117
 118B<Directory> - Path to the Git working directory in its usual setup. This
 119is just for convenient setting of both C<Repository> and C<WorkingCopy>
 120at once: If the directory as a C<.git> subdirectory, C<Repository> is pointed
 121to the subdirectory and the directory is assumed to be the working copy.
 122If the directory does not have the subdirectory, C<WorkingCopy> is left
 123undefined and C<Repository> is pointed to the directory itself.
 124
 125B<GitPath> - Path to the C<git> binary executable. By default the C<$PATH>
 126is searched for it.
 127
 128You should not use both C<Directory> and either of C<Repository> and
 129C<WorkingCopy> - the results of that are undefined.
 130
 131Alternatively, a directory path may be passed as a single scalar argument
 132to the constructor; it is equivalent to setting only the C<Directory> option
 133field.
 134
 135Calling the constructor with no options whatsoever is equivalent to
 136calling it with C<< Directory => '.' >>.
 137
 138=cut
 139
 140sub repository {
 141        my $class = shift;
 142        my @args = @_;
 143        my %opts = ();
 144        my $self;
 145
 146        if (defined $args[0]) {
 147                if ($#args % 2 != 1) {
 148                        # Not a hash.
 149                        $#args == 0 or croak "bad usage";
 150                        %opts = (Directory => $args[0]);
 151                } else {
 152                        %opts = @args;
 153                }
 154
 155                if ($opts{Directory}) {
 156                        -d $opts{Directory} or croak "Directory not found: $!";
 157                        if (-d $opts{Directory}."/.git") {
 158                                # TODO: Might make this more clever
 159                                $opts{WorkingCopy} = $opts{Directory};
 160                                $opts{Repository} = $opts{Directory}."/.git";
 161                        } else {
 162                                $opts{Repository} = $opts{Directory};
 163                        }
 164                        delete $opts{Directory};
 165                }
 166        }
 167
 168        $self = { opts => \%opts };
 169        bless $self, $class;
 170}
 171
 172
 173=back
 174
 175=head1 METHODS
 176
 177=over 4
 178
 179=item command ( COMMAND [, ARGUMENTS... ] )
 180
 181Execute the given Git C<COMMAND> (specify it without the 'git-'
 182prefix), optionally with the specified extra C<ARGUMENTS>.
 183
 184The method can be called without any instance or on a specified Git repository
 185(in that case the command will be run in the repository context).
 186
 187In scalar context, it returns all the command output in a single string
 188(verbatim).
 189
 190In array context, it returns an array containing lines printed to the
 191command's stdout (without trailing newlines).
 192
 193In both cases, the command's stdin and stderr are the same as the caller's.
 194
 195=cut
 196
 197sub command {
 198        my $fh = command_pipe(@_);
 199
 200        if (not defined wantarray) {
 201                _cmd_close($fh);
 202
 203        } elsif (not wantarray) {
 204                local $/;
 205                my $text = <$fh>;
 206                _cmd_close($fh);
 207                return $text;
 208
 209        } else {
 210                my @lines = <$fh>;
 211                _cmd_close($fh);
 212                chomp @lines;
 213                return @lines;
 214        }
 215}
 216
 217
 218=item command_oneline ( COMMAND [, ARGUMENTS... ] )
 219
 220Execute the given C<COMMAND> in the same way as command()
 221does but always return a scalar string containing the first line
 222of the command's standard output.
 223
 224=cut
 225
 226sub command_oneline {
 227        my $fh = command_pipe(@_);
 228
 229        my $line = <$fh>;
 230        _cmd_close($fh);
 231
 232        chomp $line;
 233        return $line;
 234}
 235
 236
 237=item command_pipe ( COMMAND [, ARGUMENTS... ] )
 238
 239Execute the given C<COMMAND> in the same way as command()
 240does but return a pipe filehandle from which the command output can be
 241read.
 242
 243=cut
 244
 245sub command_pipe {
 246        my ($self, $cmd, @args) = _maybe_self(@_);
 247
 248        $cmd =~ /^[a-z0-9A-Z_-]+$/ or croak "bad command: $cmd";
 249
 250        my $pid = open(my $fh, "-|");
 251        if (not defined $pid) {
 252                croak "open failed: $!";
 253        } elsif ($pid == 0) {
 254                _cmd_exec($self, $cmd, @args);
 255        }
 256        return $fh;
 257}
 258
 259
 260=item command_noisy ( COMMAND [, ARGUMENTS... ] )
 261
 262Execute the given C<COMMAND> in the same way as command() does but do not
 263capture the command output - the standard output is not redirected and goes
 264to the standard output of the caller application.
 265
 266While the method is called command_noisy(), you might want to as well use
 267it for the most silent Git commands which you know will never pollute your
 268stdout but you want to avoid the overhead of the pipe setup when calling them.
 269
 270The function returns only after the command has finished running.
 271
 272=cut
 273
 274sub command_noisy {
 275        my ($self, $cmd, @args) = _maybe_self(@_);
 276
 277        $cmd =~ /^[a-z0-9A-Z_-]+$/ or croak "bad command: $cmd";
 278
 279        my $pid = fork;
 280        if (not defined $pid) {
 281                croak "fork failed: $!";
 282        } elsif ($pid == 0) {
 283                _cmd_exec($self, $cmd, @args);
 284        }
 285        if (waitpid($pid, 0) > 0 and $? != 0) {
 286                croak "exit status: $?";
 287        }
 288}
 289
 290
 291=item exec_path ()
 292
 293Return path to the git sub-command executables (the same as
 294C<git --exec-path>). Useful mostly only internally.
 295
 296Implementation of this function is very fast; no external command calls
 297are involved.
 298
 299=cut
 300
 301# Implemented in Git.xs.
 302
 303
 304=item hash_object ( FILENAME [, TYPE ] )
 305
 306=item hash_object ( FILEHANDLE [, TYPE ] )
 307
 308Compute the SHA1 object id of the given C<FILENAME> (or data waiting in
 309C<FILEHANDLE>) considering it is of the C<TYPE> object type (C<blob>
 310(default), C<commit>, C<tree>).
 311
 312In case of C<FILEHANDLE> passed instead of file name, all the data
 313available are read and hashed, and the filehandle is automatically
 314closed. The file handle should be freshly opened - if you have already
 315read anything from the file handle, the results are undefined (since
 316this function works directly with the file descriptor and internal
 317PerlIO buffering might have messed things up).
 318
 319The method can be called without any instance or on a specified Git repository,
 320it makes zero difference.
 321
 322The function returns the SHA1 hash.
 323
 324Implementation of this function is very fast; no external command calls
 325are involved.
 326
 327=cut
 328
 329# Implemented in Git.xs.
 330
 331
 332=back
 333
 334=head1 TODO
 335
 336This is still fairly crude.
 337We need some good way to report errors back except just dying.
 338
 339=head1 COPYRIGHT
 340
 341Copyright 2006 by Petr Baudis E<lt>pasky@suse.czE<gt>.
 342
 343This module is free software; it may be used, copied, modified
 344and distributed under the terms of the GNU General Public Licence,
 345either version 2, or (at your option) any later version.
 346
 347=cut
 348
 349
 350# Take raw method argument list and return ($obj, @args) in case
 351# the method was called upon an instance and (undef, @args) if
 352# it was called directly.
 353sub _maybe_self {
 354        # This breaks inheritance. Oh well.
 355        ref $_[0] eq 'Git' ? @_ : (undef, @_);
 356}
 357
 358# When already in the subprocess, set up the appropriate state
 359# for the given repository and execute the git command.
 360sub _cmd_exec {
 361        my ($self, @args) = @_;
 362        if ($self) {
 363                $self->{opts}->{Repository} and $ENV{'GIT_DIR'} = $self->{opts}->{Repository};
 364                $self->{opts}->{WorkingCopy} and chdir($self->{opts}->{WorkingCopy});
 365        }
 366        my $git = $self->{opts}->{GitPath};
 367        $git ||= 'git';
 368        exec ($git, @args) or croak "exec failed: $!";
 369}
 370
 371# Close pipe to a subprocess.
 372sub _cmd_close {
 373        my ($fh) = @_;
 374        if (not close $fh) {
 375                if ($!) {
 376                        # It's just close, no point in fatalities
 377                        carp "error closing pipe: $!";
 378                } elsif ($? >> 8) {
 379                        croak "exit status: ".($? >> 8);
 380                }
 381                # else we might e.g. closed a live stream; the command
 382                # dying of SIGPIPE would drive us here.
 383        }
 384}
 385
 386
 387# Trickery for .xs routines: In order to avoid having some horrid
 388# C code trying to do stuff with undefs and hashes, we gate all
 389# xs calls through the following and in case we are being ran upon
 390# an instance call a C part of the gate which will set up the
 391# environment properly.
 392sub _call_gate {
 393        my $xsfunc = shift;
 394        my ($self, @args) = _maybe_self(@_);
 395
 396        if (defined $self) {
 397                # XXX: We ignore the WorkingCopy! To properly support
 398                # that will require heavy changes in libgit.
 399
 400                # XXX: And we ignore everything else as well. libgit
 401                # at least needs to be extended to let us specify
 402                # the $GIT_DIR instead of looking it up in environment.
 403                #xs_call_gate($self->{opts}->{Repository});
 404        }
 405
 406        &$xsfunc(@args);
 407}
 408
 409sub AUTOLOAD {
 410        my $xsname;
 411        our $AUTOLOAD;
 412        ($xsname = $AUTOLOAD) =~ s/.*:://;
 413        croak "&Git::$xsname not defined" if $xsname =~ /^xs_/;
 414        $xsname = 'xs_'.$xsname;
 415        _call_gate(\&$xsname, @_);
 416}
 417
 418sub DESTROY { }
 419
 420
 4211; # Famous last words