NAME

Doit::Git - commands for dealing with the git revision control system

SYNOPSIS

use Doit;
my $doit = Doit->init;
$doit->add_component('git');

$doit->git_repo_update(
    repository => 'https://github.com/eserte/Doit.git',
    directory  => '/path/to/workdir',
);

my $status = $doit->git_short_status(
    directory       => '/path/to/workdir',
    untracked_files => 'no',
);

my $directory = $doit->git_root;
my $sha1      = $doit->git_get_commit_hash;
my @files     = $doit->git_get_commit_files;
my @files     = $doit->git_get_changed_files;
my $boolean   = $doit->git_is_shallow;
my $branch    = $doit->git_current_branch;
my $dbranch   = $doit->git_get_default_branch;

$self->git_config(
    key       => 'user.email',
);
$self->git_config(
    key       => 'user.email',
    val       => 'somebody@example.com',
);
$self->git_config(
    key       => 'branch.master.rebase',
    unset     => '1,
);

DESCRIPTION

Doit::Git is a Doit component providing commands for dealing with the git revision control system. It has to be added to a script using Doit's add_component:

$doit->add_component('git');

DOIT COMMANDS

The following commands are added to the Doit runner object:

git_repo_update

$doit->git_repo_update(
    repository              => $git_url,
    directory               => $local_directory,
    repository_aliases      => [$git_url ...],
    branch                  => $branch,
    allow_remote_url_change => $boolean,
    origin                  => $nickname,
    refresh                 => 'always', # or 'never'
    clone_opts              => [...],
    quiet                   => $boolean,
);

Make sure that the given git repository $git_url is checked out (or refreshed) in the local directory $local_directory. This is done either by git-clone(1) a non-existent local repository, or by using git-fetch(1) resp. git-pull(1) for an existent local repository. Only repository and directory are mandatory options.

For existing repositories the list in repository_aliases is accepted as equivalent URLs (say, a https://... and an equivalent git://... URL). If none matches, then an exception will be thrown, unless allow_remote_url_change is set to a true value — in this case the remote URL will be adapted.

The default remote name origin may be changed by using the origin option.

If the branch option is given, then make sure that $branch is checkout out. There's some heuristics to detect detached branches and do the right thing if updates are requested.

If refresh is set to never, then only git-clone will be done for non-existent local repositories. The default is always, which means that an existing repository will be updated using git-fetch and git-pull.

clone_opts is an array ref with options which will be passed to git-clone. For existing repositories this does nothing. A common usage might be:

clone_opts => ['--depth=1'],

If quiet is set to a true value, then some operations are quiet (currently the git-fetch command).

Return 1 if there were some changes done (git-clone or git-pull was executed), otherwise 0.

git_config

my $changed = $doit->git_config(
    directory => $directory,
    key       => $key,
    val       => $val,
);
my $changed = $doit->git_config(
    directory => $directory,
    key       => $key,
    unset     => 1,
);

If $val is defined, then make sure that the git config $key has the specified value $val.

If unset is set to a true value, then make sure that the git config $key is unset (absent).

If neither of both is specified, then git_config turns into an informational command (see below).

In all cases directory may be set to a $directory, otherwise the current working directory is used. The command fails if the specified directory is not a git directory.

Note that git_config handles only simple (but common) cases. See git-config(1) for the complete possibilities of git's configuration system.

DOIT INFORMATIONAL COMMANDS

The informational commands listed below are added to the Doit runner object. Informational commands also run in dry-run mode. All commands fail if operating on a non-git directory.

git_short_status

my $status = $doit->git_short_status(
    directory       => $directory,
    untracked_files => 'normal', # or 'no'
);

Return an indicator about the git working directory status of the given $directory, or the current working directory if directory is not set. $status may have the following values:

<<

Changed tracked files exist in the working directory (i.e. git-add(1) calls are missing).

<

Local repository is newer than remote (i.e. a git-push(1) call is missing).

(the empty string)

Local and remote are in sync (but maybe a git-fetch(1) call has to be done to refresh the remote status).

>

Remote is newer than local (i.e. a git-pull(1) or git-merge(1) resp. git-rebase(1) call is missing).

<>

Remote and local diverged.

Additionally, if untracked_files is set to normal (which is the default), then the presence of * in the string (located between < and >) indicates that there are untracked files. If untracked_files is set to no, then * will not appear in the status string. Examples:

<<*  uncommitted and untracked files
<*>  remote and local diverged, and there are untracked files

There's support for git-svn(1) repositories (but there's currently no test for this).

git_root

my $directory = $doit->git_root(
    directory => $directory,
);

Return the top directory of the git checkout for the given directory $directory, or the current working directory if directory is not given. Fail if the used directory is not git-controlled.

git_get_commit_hash

    my $sha1 = $doit->git_get_commit_hash(
        directory => $directory,
	commit    => $committish,
    );

Return the SHA1 of the git checkout for the given directory $directory, or the current working directory if directory is not given.

If the optional commit is set, then return the SHA1 for the given commit --- usually a branch or tag, but may also be used to expand a abbreviated SHA1 to a full one.

git_get_commit_files

my @files = $doit->git_get_commit_files(
    directory => $directory,
    commit    => $committish,
);

Return the list of changed files of the named commit (or HEAD, if not specified) for the given directory $directory (or the current working directory if not specified).

git_get_changed_files

    my @files = $doit->git_get_changed_files(
        directory => $directory,
	ignore_untracked => $boolean,
    );

Return the list of changed files (uncommitted or untracked) in the given directory $directory (or the current working directory if not specified).

If ignore_untracked is set to a true value, then untracked files are ignored.

git_is_shallow

my @files = $doit->git_is_shallow(
    directory => $directory,
);

Return 1 if the given directory $directory (or the current working directory if not specified) is a "shallow" directory, otherwise return 0.

Implementation note: then existence of the file .git/shallow is checked.

git_current_branch

my @files = $doit->git_current_branch(
    directory => $directory,
);

my %info;
my @files = $doit->git_current_branch(
    directory => $directory,
    info_ref  => \%info,
);

Return the current branch in the given directory $directory (or the current working directory if not specified).

If info_ref is specified, then it should point to a hash reference, which is filled with the following keys:

detached

Set to a true value if the current branch is a detached one, otherwise it's set to a false value or is missing.

fallback

Set to git-status if the function walked into fallback code using git status and parsing its output. Otherwise it is missing. Mainly used for internal testing purposes.

git_get_default_branch

my $dbranch = $doit->git_get_default_branch(
    directory => $directory,
    origin    => $nickname,
    method    => $method, # "remote", "symbolic-ref", or an array ref with possible values
);

Return the default branch in the given directory $directory (or the current working directory if not specified).

By default, the remote method is used, which may access a remote system and thus be slow. Another possible method is symbolic-ref, which uses locally available information and is thus faster, but may return a wrong or no result at all in some cases.

May fail if the default branch cannot be determined.

git_config

git_config comes it several flavors, for just getting config values (which is just an informational command, running also in dry-run mode) and setting/changing or unsetting values.

git_config (informational command)

my $val = $doit->git_config(
    directory => $directory,
    key       => $key,
    all       => 0, # default
);
my @vals = $doit->git_config(
    directory => $directory,
    key       => $key,
    all       => 1,
);

Return the current value of $key, or undef if $key does not exist. If $key has multiple values, then the last value is returned (which matches the behavior of git config --get).

If all is set to a true value, then return a list of all values if the specified $key has multiple values (by using git config --get-all internally).

directory may be set to a $directory, otherwise the current working directory is used for running git-config(1).

git_config (setting values)

my $val = $doit->git_config(
    directory => $directory,
    key       => $key,
    val       => $val,
);

Set the git config of $key to $val. If $val is an array reference, then set or replace multiple values. As as special case, if $val is the empty array reference, then the setting will be deleted (which is roughly equivalent to the git config otpion --unset-all.

Return 1 if a change was done, otherwise 0.

git_config (unsetting values)

    my $val = $doit->git_config(
        directory => $directory,
        key       => $key,
	unset     => 1,
    );
    my $val = $doit->git_config(
        directory => $directory,
        key       => $key,
	unset     => 1,
	all       => 1,
    );
    my $val = $doit->git_config(
        directory => $directory,
        key       => $key,
	unset     => 1,
        val       => $val,
    );

Unset values if unset => 1 is specified. If neither val nor all is specified, a single-value config is assumed and the value is removed. git may warn if multiple values exist. If all is specified, then remove all values for this config key. If val is specified, then remove just the specified value.

Return 1 if a change was done, otherwise 0.

AUTHOR

Slaven Rezic <srezic@cpan.org>

COPYRIGHT

Copyright (c) 2017 Slaven Rezic. All rights reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

SEE ALSO

Doit, git(1).