The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
NAME
    Git::Bunch - Manage gitbunch directory (directory which contain git
    repos)

VERSION
    This document describes version 0.38 of Git::Bunch (from Perl
    distribution Git-Bunch), released on 2014-07-18.

SYNOPSIS
    To check the status of bunch (will do a 'git status' for each git repo
    inside the bunch and report which repos are 'unclean', e.g. needs
    commit, has untracked files, etc):

     % gitbunch check ~/repos

    To synchronize bunch to another (will do a 'git pull/push' for each git
    repo, and do an rsync for everything else):

     % gitbunch sync ~/repos /mnt/laptop/repos

DESCRIPTION
    A gitbunch or bunch directory is just a term I coined to refer to a
    directory which contains, well, a bunch of git repositories. It can also
    contain other stuffs like files and non-git repositories (but they must
    be dot-dirs). Example:

     repos/            -> a gitbunch dir
       proj1/          -> a git repo
       proj2/          -> ditto
       perl-Git-Bunch/ -> ditto
       ...
       .foo/           -> a non-git dir
       README.txt      -> file

    A little bit of history: after git got popular, in 2008 I started using
    it for software projects, replacing Subversion and Bazaar. Soon, I moved
    everything to git: notes & writings, Emacs .org agenda files,
    configuration, even temporary downloads/browser-saved HTML files.
    Currently, except large media files, all my personal data resides in git
    repositories. I put them all in ~/repos (and add symlinks to various
    places for convenience). This setup makes it easy to sync to laptops,
    backup to disk, etc. Git::Bunch is the library/script I wrote to do
    this.

    See also File::RsyBak, which I wrote to backup everything else.

FUNCTIONS
  check_bunch(%args) -> [status, msg, result, meta]
    Check status of git repositories inside gitbunch directory.

    Will perform a 'git status' for each git repositories inside the bunch
    and report which repositories are clean/unclean.

    Will die if can't chdir into bunch or git repository.

    Arguments ('*' denotes required arguments):

    *   exclude_files => *bool*

        Exclude files from processing.

        This only applies to "sync_bunch" operations. Operations like
        "check_bunch" and "exec_bunch" already ignore these and only operate
        on git repos.

    *   exclude_non_git_dirs => *bool*

        Exclude non-git dirs from processing.

        This only applies to and "sync_bunch" operations. Operations like
        "check_bunch" and "exec_bunch" already ignore these and only operate
        on git repos.

    *   exclude_repos => *array*

        Exclude some repos from processing.

    *   exclude_repos_pat => *str*

        Specify regex pattern of repos to exclude.

    *   include_repos => *array*

        Specific git repos to sync, if not specified all repos in the bunch
        will be processed.

    *   include_repos_pat => *str*

        Specify regex pattern of repos to include.

    *   repo => *str*

        Only process a single repo.

    *   sort => *str* (default: "-commit-timestamp")

        Order entries in bunch.

        "commit-timestamp" (and "-commit-timestamp") compares the timestamp
        of ".git/commit-timestamp" file in each repo. Repos or dirs not
        having this file will be processed later. You can touch these
        ".git/commit-timestamp" files in your post-commit script, for
        example. This allows sorting recently committed repos more cheaply
        (compared to doing "git log -1").

    *   source* => *str*

        Directory to check.

    Return value:

    Returns an enveloped result (an array).

    First element (status) is an integer containing HTTP status code (200
    means OK, 4xx caller error, 5xx function error). Second element (msg) is
    a string containing error message, or 'OK' if status is 200. Third
    element (result) is optional, the actual result. Fourth element (meta)
    is called result metadata and is optional, a hash that contains extra
    information.

  exec_bunch(%args) -> [status, msg, result, meta]
    Execute a command for each repo in the bunch.

    For each git repository in the bunch, will chdir to it and execute
    specified command.

    Arguments ('*' denotes required arguments):

    *   command* => *str*

        Command to execute.

    *   exclude_files => *bool*

        Exclude files from processing.

        This only applies to "sync_bunch" operations. Operations like
        "check_bunch" and "exec_bunch" already ignore these and only operate
        on git repos.

    *   exclude_non_git_dirs => *bool*

        Exclude non-git dirs from processing.

        This only applies to and "sync_bunch" operations. Operations like
        "check_bunch" and "exec_bunch" already ignore these and only operate
        on git repos.

    *   exclude_repos => *array*

        Exclude some repos from processing.

    *   exclude_repos_pat => *str*

        Specify regex pattern of repos to exclude.

    *   include_repos => *array*

        Specific git repos to sync, if not specified all repos in the bunch
        will be processed.

    *   include_repos_pat => *str*

        Specify regex pattern of repos to include.

    *   repo => *str*

        Only process a single repo.

    *   sort => *str* (default: "-commit-timestamp")

        Order entries in bunch.

        "commit-timestamp" (and "-commit-timestamp") compares the timestamp
        of ".git/commit-timestamp" file in each repo. Repos or dirs not
        having this file will be processed later. You can touch these
        ".git/commit-timestamp" files in your post-commit script, for
        example. This allows sorting recently committed repos more cheaply
        (compared to doing "git log -1").

    *   source* => *str*

        Directory to check.

    Return value:

    Returns an enveloped result (an array).

    First element (status) is an integer containing HTTP status code (200
    means OK, 4xx caller error, 5xx function error). Second element (msg) is
    a string containing error message, or 'OK' if status is 200. Third
    element (result) is optional, the actual result. Fourth element (meta)
    is called result metadata and is optional, a hash that contains extra
    information.

  sync_bunch(%args) -> [status, msg, result, meta]
    Synchronize bunch to another bunch.

    For each git repository in the bunch, will perform a 'git pull/push' for
    each branch. If repository in destination doesn't exist, it will be
    rsync-ed first from source. When 'git pull' fails, will exit to let you
    fix the problem manually.

    For all other non-git repos, will simply synchronize by one-way rsync.

    Arguments ('*' denotes required arguments):

    *   backup => *bool*

        Whether doing backup to target.

        This setting lets you express that you want to perform synchronizing
        to a backup target, and that you do not do work on the target. Thus,
        you do not care about uncommitted or untracked files/dirs in the
        target repos (might happen if you also do periodic copying of repos
        to backup using cp/rsync). When this setting is turned on, the
        function will first do a "git clean -f -d" (to delete untracked
        files/dirs) and then "git checkout ." (to discard all uncommitted
        changes). This setting will also implicitly turn on "create_bare"
        setting (unless that setting has been explicitly enabled/disabled).

    *   create_bare_target => *bool*

        Whether to create bare git repo when target does not exist.

        When target repo does not exist, gitbunch can either copy the source
        repo using "rsync" (the default, if this setting is undefined), or
        it can create target repo with "git init --bare" (if this setting is
        set to 1), or it can create target repo with "git init" (if this
        setting is set to 0).

        Bare git repositories contain only contents of the .git folder
        inside the directory and no working copies of your source files.

        Creating bare repos are apt for backup purposes since they are more
        space-efficient.

        Non-repos will still be copied/rsync-ed.

    *   delete_branch => *bool* (default: 0)

        Whether to delete branches in dest repos not existing in source
        repos.

    *   exclude_files => *bool*

        Exclude files from processing.

        This only applies to "sync_bunch" operations. Operations like
        "check_bunch" and "exec_bunch" already ignore these and only operate
        on git repos.

    *   exclude_non_git_dirs => *bool*

        Exclude non-git dirs from processing.

        This only applies to and "sync_bunch" operations. Operations like
        "check_bunch" and "exec_bunch" already ignore these and only operate
        on git repos.

    *   exclude_repos => *array*

        Exclude some repos from processing.

    *   exclude_repos_pat => *str*

        Specify regex pattern of repos to exclude.

    *   include_repos => *array*

        Specific git repos to sync, if not specified all repos in the bunch
        will be processed.

    *   include_repos_pat => *str*

        Specify regex pattern of repos to include.

    *   repo => *str*

        Only process a single repo.

    *   rsync_opt_maintain_ownership => *bool* (default: 0)

        Whether or not, when rsync-ing from source, we use -a (= -rlptgoD)
        or -rlptD (-a minus -go).

        Sometimes using -a results in failure to preserve permission modes
        on sshfs-mounted filesystem, while -rlptD succeeds, so by default we
        don't maintain ownership. If you need to maintain ownership (e.g.
        you run as root and the repos are not owned by root), turn this
        option on.

    *   sort => *str* (default: "-commit-timestamp")

        Order entries in bunch.

        "commit-timestamp" (and "-commit-timestamp") compares the timestamp
        of ".git/commit-timestamp" file in each repo. Repos or dirs not
        having this file will be processed later. You can touch these
        ".git/commit-timestamp" files in your post-commit script, for
        example. This allows sorting recently committed repos more cheaply
        (compared to doing "git log -1").

    *   source* => *str*

        Directory to check.

    *   target* => *str*

        Destination bunch.

    Return value:

    Returns an enveloped result (an array).

    First element (status) is an integer containing HTTP status code (200
    means OK, 4xx caller error, 5xx function error). Second element (msg) is
    a string containing error message, or 'OK' if status is 200. Third
    element (result) is optional, the actual result. Fourth element (meta)
    is called result metadata and is optional, a hash that contains extra
    information.

FAQ
TODO
    *   Can't handle bare source repos

    *   Sync-ing to bare repos (e.g. with --backup) still produces error
        messages

        Although the sync process succeeds, the error messages (like "fatal:
        Not a git repository") might be confusing.

SEE ALSO
    mr, http://joeyh.name/code/mr/ . You probably want to use this instead.
    mr supports other control version software aside from git, doesn't
    restrict you to put all your repos in one directory, supports more
    operations, and has been developed since 2007. Had I known about mr, I
    probably wouldn't have started Git::Bunch. On the other hand, Git::Bunch
    is simpler (I think), doesn't require any config file, and can copy/sync
    files/directories not under source control. I mainly use Git::Bunch to
    quickly: 1) check whether there are any of my repositories which have
    uncommitted changes; 2) synchronize (pull/push) to other locations. I
    put all my data in one big gitbunch directory; I find it simpler.
    Git::Bunch works for me and I use it daily.

HOMEPAGE
    Please visit the project's homepage at
    <https://metacpan.org/release/Git-Bunch>.

SOURCE
    Source repository is at <https://github.com/sharyanto/perl-Git-Bunch>.

BUGS
    Please report any bugs or feature requests on the bugtracker website
    <https://rt.cpan.org/Public/Dist/Display.html?Name=Git-Bunch>

    When submitting a bug or request, please include a test-file or a patch
    to an existing test-file that illustrates the bug or desired feature.

AUTHOR
    Steven Haryanto <stevenharyanto@gmail.com>

COPYRIGHT AND LICENSE
    This software is copyright (c) 2014 by Steven Haryanto.

    This is free software; you can redistribute it and/or modify it under
    the same terms as the Perl 5 programming language system itself.