[Bps-public-commit] git-sync branch, master, updated. 784b144a03a0246a1a9c2832e90c8fc5b7766e57

Alex M Vandiver alexmv at bestpractical.com
Sat Nov 21 16:29:45 EST 2009


The branch, master has been updated
  discards  8dc5a06a6a5aeb3d73a79b02541a84f6d851d5bf (commit)
       via  784b144a03a0246a1a9c2832e90c8fc5b7766e57 (commit)
       via  3263bd94a7df0abeaad95d0753606b0b477ad507 (commit)
       via  4273ad2c115a8f45670e70ef01509698fc120c77 (commit)
       via  ae7281dfd903beb1a3f00447c52fa5f76ba70822 (commit)
       via  ce8e6164f47ec942425ea610bb2dbede1d1dd15f (commit)
       via  c1e8123a27c728238ffd5522799c93c40abb4df2 (commit)
       via  8bf9e5d5ec7c26432462e37ba7ab47f520a04558 (commit)
       via  9da5111cb94e7af084b0390f0017f6fedc34731f (commit)
       via  73952e2eebf3028d87a68b54103dbe83e1fb03c2 (commit)
       via  c09a8c304e976248db439b61e73f1e40f45ab059 (commit)
       via  4c5330f3b3bdfcef2d1b5b0e830ebefa9f9c3191 (commit)
       via  766f06d02f1cecc51c7ae8746022f2cd9c03112a (commit)
       via  24d13afd79710e21772debd454f3137ac1f44756 (commit)
       via  abd5dac38563a8a84f1b95fd7653a91b8d451e9d (commit)
       via  2b3f7d3f2caba8bd58943992a7fd1e763d7a2ff4 (commit)
       via  4deb40589848d22e055d08612d420fcbef7220db (commit)
       via  59123d1e1a8c39f21ae9afc0c77d60d8b1571908 (commit)
       via  e46b1a09d255e660a0358032e21d43455cd02a0d (commit)
       via  7d9fcfc0dc554634956634c8c11901d37be4b553 (commit)
       via  10514f8140e6e39b43b777433a296603fd824d96 (commit)
       via  8cc12fb673f3e31d019af1eb6ae5bcb802572539 (commit)
       via  aa447f1835ee15f2343fedad3c6380c8125c8a5d (commit)
       via  0754d02e75acab9fe3fcd3b5ccdc3787c92209ab (commit)
       via  279fa342d7a6964b1ad65cb2bd4e4a590fc124a8 (commit)
       via  885dcf7aaa29fa4f756c9560d9e18ce22a23f4d6 (commit)
       via  ba4be5a9d02dcedcc655112ea2e3f74ff2d8e0ed (commit)
       via  8ed04d08b7d12179db4384c65e05fdff36b8ad1b (commit)
       via  9fd8b54b557396137b29b67b6c61b5edcb4b1120 (commit)
       via  314dca3448f468b3b59c44c3c544b36d81481a89 (commit)
       via  595d4b6e39eed6c8ebd7a9cdcceaea4ca6e02642 (commit)
       via  e46db7470958385f8c7639e4ac588ac55c7bbe15 (commit)
       via  d3ba93894d9a5a69de5fd96943a168cbdb85e425 (commit)
       via  ce7538335f3eb09493cdb41fcbbf2eadeeff4c6f (commit)
       via  0eeb0c7862856af8259a3a9c084d86326b361479 (commit)
       via  4bd151873725406a7c10dffa0e68dd8aea02ea4e (commit)
       via  2cbd74eaf34350fc1162cec97ed8557bb18f4daf (commit)
       via  92c71761417cb97090f0056ebb70ecd4e966f920 (commit)
       via  cf91430d27ca2098e87c55cbcac04343323735a3 (commit)
       via  a9be3ddcf0153c79535b45afd236d4fd9ade37a1 (commit)
       via  2462f7ff0c80e189c941c3381c9ff618d5666928 (commit)
       via  6dc8b1cd097f69b8367b982e6c92413d153c443d (commit)
       via  0e2352ee036e46a3e92c565e96308c78b39b30b9 (commit)
       via  36d1b9d95260b01028ad05ff6f5e33ae07f615db (commit)
       via  09f8873bc027ef1ffc79a56f1e9c07ec4b92af27 (commit)
       via  135fe9911c4f1249a2b20b77b0650cd7b85ba3e1 (commit)
       via  d0131e559d473bf328d7bf289487c5f11eb17faa (commit)
       via  4c1040f93580634383011e8a5ea62a0056a308d2 (commit)
       via  2fc211e1ea297ca020a0cd437e2c0c497196202a (commit)
       via  48b5a3eea425c64fde8ad3b2892997058a8409d2 (commit)
       via  b1f609ee2c2fb3f07c908cc20d3873e98e03f694 (commit)

This update added new revisions after undoing existing revisions.  That is
to say, the old revision is not a strict subset of the new revision.  This
situation occurs when you --force push a change and generate a repository
containing something like this:

 * -- * -- B -- O -- O -- O (8dc5a06a6a5aeb3d73a79b02541a84f6d851d5bf)
            \
             N -- N -- N (784b144a03a0246a1a9c2832e90c8fc5b7766e57)

When this happens we assume that you've already had alert emails for all
of the O revisions, and so we here report only the revisions in the N
branch from the common base, B.

Summary of changes:
 git-sync |  311 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 311 insertions(+), 0 deletions(-)
 create mode 100755 git-sync

- Log -----------------------------------------------------------------
commit b1f609ee2c2fb3f07c908cc20d3873e98e03f694
Author: jesse <jesse at bestpractical.com>
Date:   Tue Apr 14 23:54:22 2009 -0400

    First post

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e69de29

commit 48b5a3eea425c64fde8ad3b2892997058a8409d2
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Jul 10 18:13:06 2009 -0400

    Add smarter sync script

diff --git a/git-sync b/git-sync
new file mode 100644
index 0000000..2bc7d10
--- /dev/null
+++ b/git-sync
@@ -0,0 +1,85 @@
+#!/usr/bin/perl
+
+use Config::GitLike::Git;
+use Git;
+use strict;
+use warnings;
+
+my %conf = Config::GitLike::Git->new->load;
+
+my %sync;
+for (keys %conf) {
+    next unless /^sync\.(?:(.*?)\.)?(.*)$/;
+    my ($section, $var) = ($1, $2);
+    $section = "" unless defined $section;
+    $sync{$section}{$var} = $conf{$_};
+}
+
+my %seen;
+for my $name (keys %sync) {
+    print "Syncing" . (length $name ? " $name" : "")."\n";
+    unless ($sync{$name}{host}) {
+        warn "No 'host' set, skipping!\n";
+        next;
+    }
+    unless ($sync{$name}{path}) {
+        warn "No 'path' set, skipping!\n";
+        next;
+    }
+    unless ($sync{$name}{into}) {
+        warn "No 'into' set, skipping!\n";
+        next;
+    }
+    my @paths = ref $sync{$name}{path} ? @{$sync{$name}{path}} : ($sync{$name}{path});
+    for my $path (@paths) {
+        my @list = `ssh $sync{$name}{host} ls $path`;
+        warn("Listing returned ".($? >> 8).", skipping!\n") and next if $?;
+        for my $reponame (@list) {
+            $reponame =~ s/(\.git)?\n?$//;
+            my $root = "$sync{$name}{into}/$reponame";
+            if ($seen{$root}) {
+                warn "Duplicate repository sync location: $seen{$root} and $path/$reponame\n";
+                next;
+            }
+            $seen{$root} = "$path/$reponame";
+
+            if (-e $root) {
+                # Already exists, fetch and possibly rebase
+                my $repo = eval { Git->repository(Directory => $root) };
+                warn("$root not a git repository? $@\n") and next unless $repo;
+
+                warn "Fetching $reponame\n";
+                eval { $repo->command( "fetch" ); };
+                next if $@;
+
+                my $status = "";
+                my ($fh, $ctx) = $repo->command_output_pipe('status');
+                $status .= $_ while (<$fh>);
+                eval {$repo->command_close_pipe($fh, $ctx);};
+
+                # Rebase if there are no changes, it is on a tracking
+                # branch, and the result would be a fast-forward
+                if ($status =~ /^# Your branch is behind '.*?' by \d commits, and can be fast-forwarded/m
+                        and $status =~ /^nothing to commit/m) {
+                    warn "Pulling local working copy\n";
+                    # git-pull is a shell script, unfortunately, and
+                    # thus can't be run via $repo->command( "pull" )
+                    chdir($root);
+                    system("git pull");
+                }
+            } else {
+                Git::command_noisy( clone => "$sync{$name}{host}:$path/$reponame", $root );
+                Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )
+                      if $sync{$name}{email};
+            }
+        }
+    }
+}
+
+__END__
+[sync "bps"]
+	host = fsck.com
+	path = /git
+	path = /git-private
+	into = /home/chmrr/work/bps/git
+        email = alexmv at bestpractical.com

commit 2fc211e1ea297ca020a0cd437e2c0c497196202a
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Mon Jul 13 14:06:08 2009 -0400

    don't hardcode perl path

diff --git a/git-sync b/git-sync
old mode 100644
new mode 100755
index 2bc7d10..8c62107
--- a/git-sync
+++ b/git-sync
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/usr/bin/env perl
 
 use Config::GitLike::Git;
 use Git;

commit 4c1040f93580634383011e8a5ea62a0056a308d2
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Mon Jul 13 14:14:57 2009 -0400

    normalize spacing

diff --git a/git-sync b/git-sync
index 8c62107..4e1b238 100755
--- a/git-sync
+++ b/git-sync
@@ -78,8 +78,8 @@ for my $name (keys %sync) {
 
 __END__
 [sync "bps"]
-	host = fsck.com
-	path = /git
-	path = /git-private
-	into = /home/chmrr/work/bps/git
-        email = alexmv at bestpractical.com
+    host = fsck.com
+    path = /git
+    path = /git-private
+    into = /home/chmrr/work/bps/git
+    email = alexmv at bestpractical.com

commit d0131e559d473bf328d7bf289487c5f11eb17faa
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Mon Jul 13 14:19:28 2009 -0400

    Allow 'git sync foo' to only sync some of your repos

diff --git a/git-sync b/git-sync
index 4e1b238..76e1269 100755
--- a/git-sync
+++ b/git-sync
@@ -15,8 +15,11 @@ for (keys %conf) {
     $sync{$section}{$var} = $conf{$_};
 }
 
+my $synconly = shift ||'';
+
 my %seen;
 for my $name (keys %sync) {
+    next if ($synconly && $name ne $synconly);
     print "Syncing" . (length $name ? " $name" : "")."\n";
     unless ($sync{$name}{host}) {
         warn "No 'host' set, skipping!\n";

commit 135fe9911c4f1249a2b20b77b0650cd7b85ba3e1
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Tue Jul 14 10:16:16 2009 -0400

    tiny bit of usage doc

diff --git a/git-sync b/git-sync
index 76e1269..69ddcf1 100755
--- a/git-sync
+++ b/git-sync
@@ -1,5 +1,15 @@
 #!/usr/bin/env perl
 
+# Simple usage:
+# add the config found after __END__ to your config
+# the script will search like git does, so
+# ./.git/config, ~/.gitconfig, /etc/gitconfig
+#
+# $ git sync
+# syncs all sync sections of your config
+# $ git sync bps
+# syncs only one of the sections
+
 use Config::GitLike::Git;
 use Git;
 use strict;

commit 09f8873bc027ef1ffc79a56f1e9c07ec4b92af27
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Thu Jul 23 14:21:11 2009 -0400

    If you have a local bare repo, don't do anything other than fetch in it

diff --git a/git-sync b/git-sync
index 69ddcf1..8601b3d 100755
--- a/git-sync
+++ b/git-sync
@@ -65,6 +65,8 @@ for my $name (keys %sync) {
                 eval { $repo->command( "fetch" ); };
                 next if $@;
 
+                next if $repo->config_bool('core.bare');
+
                 my $status = "";
                 my ($fh, $ctx) = $repo->command_output_pipe('status');
                 $status .= $_ while (<$fh>);

commit 36d1b9d95260b01028ad05ff6f5e33ae07f615db
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Wed Jul 29 15:06:38 2009 -0400

    Be extra chatty when fetching changes

diff --git a/git-sync b/git-sync
index 8601b3d..c288425 100755
--- a/git-sync
+++ b/git-sync
@@ -80,7 +80,7 @@ for my $name (keys %sync) {
                     # git-pull is a shell script, unfortunately, and
                     # thus can't be run via $repo->command( "pull" )
                     chdir($root);
-                    system("git pull");
+                    system("git pull --stat");
                 }
             } else {
                 Git::command_noisy( clone => "$sync{$name}{host}:$path/$reponame", $root );

commit 0e2352ee036e46a3e92c565e96308c78b39b30b9
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Wed Jul 29 15:21:14 2009 -0400

    Before syncing a repo, check that we've not set sync.ignore
    
    useful for repos that we only want to live on diesel becuase we'll be
    using git remote to add references

diff --git a/git-sync b/git-sync
index c288425..0befa68 100755
--- a/git-sync
+++ b/git-sync
@@ -83,6 +83,8 @@ for my $name (keys %sync) {
                     system("git pull --stat");
                 }
             } else {
+                chomp(my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`);
+                next if $ignore eq 'true';
                 Git::command_noisy( clone => "$sync{$name}{host}:$path/$reponame", $root );
                 Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )
                       if $sync{$name}{email};

commit 6dc8b1cd097f69b8367b982e6c92413d153c443d
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Mon Aug 3 14:36:28 2009 -0400

    clean up warnings
    
    git config --bool doesnt.exist will return an empty value rather
    than false.

diff --git a/git-sync b/git-sync
index 0befa68..072b7a3 100755
--- a/git-sync
+++ b/git-sync
@@ -83,8 +83,8 @@ for my $name (keys %sync) {
                     system("git pull --stat");
                 }
             } else {
-                chomp(my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`);
-                next if $ignore eq 'true';
+                my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
+                next if $ignore && chomp($ignore) eq 'true';
                 Git::command_noisy( clone => "$sync{$name}{host}:$path/$reponame", $root );
                 Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )
                       if $sync{$name}{email};

commit 2462f7ff0c80e189c941c3381c9ff618d5666928
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Aug 3 15:07:04 2009 -0400

    chomp returns number of newlines removed, not new string

diff --git a/git-sync b/git-sync
index 072b7a3..e4ad7e0 100755
--- a/git-sync
+++ b/git-sync
@@ -84,7 +84,8 @@ for my $name (keys %sync) {
                 }
             } else {
                 my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
-                next if $ignore && chomp($ignore) eq 'true';
+                chomp $ignore if defined $ignore;
+                next if defined $ignore and $ignore eq 'true';
                 Git::command_noisy( clone => "$sync{$name}{host}:$path/$reponame", $root );
                 Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )
                       if $sync{$name}{email};

commit a9be3ddcf0153c79535b45afd236d4fd9ade37a1
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Thu Aug 20 14:34:34 2009 -0400

    Match git's status better
    
    You can be more than 9 commits behind
    If you were 1 commit behind, we wouldn't pull

diff --git a/git-sync b/git-sync
index e4ad7e0..53d97ea 100755
--- a/git-sync
+++ b/git-sync
@@ -74,7 +74,7 @@ for my $name (keys %sync) {
 
                 # Rebase if there are no changes, it is on a tracking
                 # branch, and the result would be a fast-forward
-                if ($status =~ /^# Your branch is behind '.*?' by \d commits, and can be fast-forwarded/m
+                if ($status =~ /^# Your branch is behind '.*?' by \d+ commits?, and can be fast-forwarded/m
                         and $status =~ /^nothing to commit/m) {
                     warn "Pulling local working copy\n";
                     # git-pull is a shell script, unfortunately, and

commit cf91430d27ca2098e87c55cbcac04343323735a3
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Aug 27 14:39:21 2009 -0400

    Purge old remote branches after sync

diff --git a/git-sync b/git-sync
index 53d97ea..2ddfa84 100755
--- a/git-sync
+++ b/git-sync
@@ -82,6 +82,9 @@ for my $name (keys %sync) {
                     chdir($root);
                     system("git pull --stat");
                 }
+
+                # Purge old tracking branches
+                $repo->command( qw/remote prune origin/ );
             } else {
                 my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
                 chomp $ignore if defined $ignore;

commit 92c71761417cb97090f0056ebb70ecd4e966f920
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Mon Oct 5 12:05:04 2009 -0400

    If you have local untracker/ignored files, still pull
    
    If there is a conflict, at least you'll be up to date (rather than 83
    commits behind)

diff --git a/git-sync b/git-sync
index 2ddfa84..60ecc85 100755
--- a/git-sync
+++ b/git-sync
@@ -75,7 +75,7 @@ for my $name (keys %sync) {
                 # Rebase if there are no changes, it is on a tracking
                 # branch, and the result would be a fast-forward
                 if ($status =~ /^# Your branch is behind '.*?' by \d+ commits?, and can be fast-forwarded/m
-                        and $status =~ /^nothing to commit/m) {
+                        and $status =~ /^nothing (?:added )?to commit/m) {
                     warn "Pulling local working copy\n";
                     # git-pull is a shell script, unfortunately, and
                     # thus can't be run via $repo->command( "pull" )

commit 2cbd74eaf34350fc1162cec97ed8557bb18f4daf
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Oct 16 22:08:13 2009 -0400

    Use pretty colors to make status of repositories clearer

diff --git a/git-sync b/git-sync
index 60ecc85..f8aa4ff 100755
--- a/git-sync
+++ b/git-sync
@@ -14,35 +14,66 @@ use Config::GitLike::Git;
 use Git;
 use strict;
 use warnings;
+use Term::ANSIColor;
 
 my %conf = Config::GitLike::Git->new->load;
 
 my %sync;
 for (keys %conf) {
-    next unless /^sync\.(?:(.*?)\.)?(.*)$/;
-    my ($section, $var) = ($1, $2);
-    $section = "" unless defined $section;
-    $sync{$section}{$var} = $conf{$_};
+    next unless /^sync\.(.*?)\.(.*)$/;
+    $sync{$1}{$2} = $conf{$_};
 }
 
-my $synconly = shift ||'';
+my @categories;
+if (@ARGV) {
+    for my $name (@ARGV) {
+        die qq{Can't find sync named "$name"\n} unless exists $sync{$name};
+        push @categories, $name;
+    }
+} else {
+    @categories = sort {exists $sync{$a}{local} <=> exists $sync{$b}{local} or $a cmp $b} keys %sync;
+}
 
 my %seen;
-for my $name (keys %sync) {
-    next if ($synconly && $name ne $synconly);
-    print "Syncing" . (length $name ? " $name" : "")."\n";
-    unless ($sync{$name}{host}) {
-        warn "No 'host' set, skipping!\n";
+for my $name (@categories) {
+    print colored("Syncing" . (length $name ? " $name" : "")."\n", "bold");
+
+    unless ($sync{$name}{into}) {
+        print colored("  No 'into' set, skipping!\n", "red");
         next;
     }
-    unless ($sync{$name}{path}) {
-        warn "No 'path' set, skipping!\n";
-        next;
+    if (exists $sync{$name}{local}) {
+        sync_all_local($name);
+    } else {
+        unless ($sync{$name}{host}) {
+            print colored("  No 'host' set, skipping!\n", "red");
+            next;
+        }
+        unless ($sync{$name}{path}) {
+            print colored("  No 'path' set, skipping!\n", "red");
+            next;
+        }
+        sync_all_remote($name);
     }
-    unless ($sync{$name}{into}) {
-        warn "No 'into' set, skipping!\n";
-        next;
+    print " "x45,"\n";
+}
+
+sub sync_all_local {
+    my $name = shift;
+    for my $root (grep {-d} <$sync{$name}{into}/*>) {
+        $root =~ m{/([^/]+)(?:\.git)?$};
+        printf "  %-40s ", $1;
+        if (exists $seen{$root}) {
+            print "\r";
+            next;
+        }
+        update($root, 0);
+        $seen{$root} = "";
     }
+}
+
+sub sync_all_remote {
+    my $name = shift;
     my @paths = ref $sync{$name}{path} ? @{$sync{$name}{path}} : ($sync{$name}{path});
     for my $path (@paths) {
         my @list = `ssh $sync{$name}{host} ls $path`;
@@ -50,53 +81,108 @@ for my $name (keys %sync) {
         for my $reponame (@list) {
             $reponame =~ s/(\.git)?\n?$//;
             my $root = "$sync{$name}{into}/$reponame";
+
+            printf "  %-40s ", $reponame;
             if ($seen{$root}) {
-                warn "Duplicate repository sync location: $seen{$root} and $path/$reponame\n";
+                print colored( "[ Already synchronized! ]\n", "red");
+                next;
+            } elsif (exists $seen{$root}) {
+                print "\r";
                 next;
             }
-            $seen{$root} = "$path/$reponame";
-
+            $seen{$root} = $name;
             if (-e $root) {
-                # Already exists, fetch and possibly rebase
-                my $repo = eval { Git->repository(Directory => $root) };
-                warn("$root not a git repository? $@\n") and next unless $repo;
-
-                warn "Fetching $reponame\n";
-                eval { $repo->command( "fetch" ); };
-                next if $@;
-
-                next if $repo->config_bool('core.bare');
-
-                my $status = "";
-                my ($fh, $ctx) = $repo->command_output_pipe('status');
-                $status .= $_ while (<$fh>);
-                eval {$repo->command_close_pipe($fh, $ctx);};
-
-                # Rebase if there are no changes, it is on a tracking
-                # branch, and the result would be a fast-forward
-                if ($status =~ /^# Your branch is behind '.*?' by \d+ commits?, and can be fast-forwarded/m
-                        and $status =~ /^nothing (?:added )?to commit/m) {
-                    warn "Pulling local working copy\n";
-                    # git-pull is a shell script, unfortunately, and
-                    # thus can't be run via $repo->command( "pull" )
-                    chdir($root);
-                    system("git pull --stat");
-                }
-
-                # Purge old tracking branches
-                $repo->command( qw/remote prune origin/ );
+                update($root, 1);
             } else {
-                my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
-                chomp $ignore if defined $ignore;
-                next if defined $ignore and $ignore eq 'true';
-                Git::command_noisy( clone => "$sync{$name}{host}:$path/$reponame", $root );
-                Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )
-                      if $sync{$name}{email};
+                new($root => $name => $reponame => $path);
             }
         }
     }
 }
 
+sub update {
+    my ($root, $force) = @_;
+
+    # Already exists, fetch and possibly rebase
+    my $repo = eval { Git->repository(Directory => $root) };
+    unless ($repo) {
+        print $force ? colored("[ Not a git repository! ]\n", "red") : "\r";
+        return;
+    }
+
+    my $gitsvn = -d $repo->repo_path . "/svn/git-svn";
+    if ($gitsvn) {
+        print colored( "[ svn ] ", "dark blue" );
+         # git-svn doesn't work with $repo->command, hate
+        `git --git-dir @{[$repo->repo_path]} svn fetch -q`;
+    } else {
+        eval { $repo->command( ["fetch"], STDERR => 0 ); } if 0;
+    }
+    print colored("[ Fetch failed! $@]\n", "red") and return if $@;
+
+    print colored("[ Bare repository ]\n", "green") and return if $repo->config_bool('core.bare');
+
+    my $status = "";
+    my ($fh, $ctx) = $repo->command_output_pipe('status');
+    $status .= $_ while (<$fh>);
+    eval {$repo->command_close_pipe($fh, $ctx);};
+
+    # Rebase if there are no changes, it is on a tracking
+    # branch, and the result would be a fast-forward
+    my ($branch) = $status =~ /^# On branch (.*)/m;
+    if ($status =~ /^# Your branch is behind '.*?' by \d+ commits?, and can be fast-forwarded/m
+            and $status =~ /^nothing (?:added )?to commit/m) {
+        # git-pull is a shell script, unfortunately, and
+        # thus can't be run via $repo->command( "pull" )
+        chdir($root);
+        print colored( "[ Pulled ($branch) ]\n", "bold green" );
+        my $pull = `git pull --stat`;
+        # Indent, and colorize (git doesn't, because we're not a tty)
+        $pull =~ s/^/    /gm;
+        $pull =~ s/^(  .*?)(\+*)(-*)$/$1.colored($2,"green").colored($3,"red")/gme;
+        print $pull;
+    } else {
+        if ($status =~ /^# Your branch and '.*?' have diverged.*?(\d+) and (\d+) different commit/sm) {
+            print colored( "[ Diverged by $1 and $2 commits ($branch) ]", "bold blue" );
+        } elsif ($status =~ /^# Your branch is ahead /m) {
+            print colored( "[ Ahead ($branch) ]", "bold blue");
+        } else {
+            print colored( "[ Up-to-date ($branch) ]", "green");
+        }
+        if ($status !~ /^nothing (?:added )?to commit/m) {
+            print colored( " [ Dirty ]", "yellow");
+        }
+        print "\n";
+    }
+
+    # Purge old tracking branches
+    $repo->command( qw/remote prune origin/ ) unless $gitsvn;
+}
+
+sub new {
+    my ($root, $name, $reponame, $path) = @_;
+    `ssh $sync{$name}{host} [ -e $path/${reponame}.git/config ]`;
+    if ($?) {
+        print "\r";
+        return;
+    }
+    my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
+    chomp $ignore if defined $ignore;
+    if (defined $ignore and $ignore eq 'true') {
+        print "\r";
+        return;
+    }
+
+    eval { Git::command( [clone => "$sync{$name}{host}:$path/$reponame", $root], STDERR => 0 ) };
+    if ($@) {
+        print colored( "[ Clone failed! ]\n", "red");
+        return;
+    }
+    Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )
+          if $sync{$name}{email};
+    print colored( "[ Cloned! ]\n", "bold green");
+}
+
 __END__
 [sync "bps"]
     host = fsck.com

commit 4bd151873725406a7c10dffa0e68dd8aea02ea4e
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 02:30:15 2009 -0400

    Existence of .git/svn/.metadata is better for detecting git-svn checkouts

diff --git a/git-sync b/git-sync
index f8aa4ff..a4a3e30 100755
--- a/git-sync
+++ b/git-sync
@@ -110,7 +110,7 @@ sub update {
         return;
     }
 
-    my $gitsvn = -d $repo->repo_path . "/svn/git-svn";
+    my $gitsvn = -e $repo->repo_path . "/svn/.metadata";
     if ($gitsvn) {
         print colored( "[ svn ] ", "dark blue" );
          # git-svn doesn't work with $repo->command, hate

commit 0eeb0c7862856af8259a3a9c084d86326b361479
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 02:33:47 2009 -0400

    Show how many commits ahead the branch is

diff --git a/git-sync b/git-sync
index a4a3e30..3156b31 100755
--- a/git-sync
+++ b/git-sync
@@ -144,8 +144,8 @@ sub update {
     } else {
         if ($status =~ /^# Your branch and '.*?' have diverged.*?(\d+) and (\d+) different commit/sm) {
             print colored( "[ Diverged by $1 and $2 commits ($branch) ]", "bold blue" );
-        } elsif ($status =~ /^# Your branch is ahead /m) {
-            print colored( "[ Ahead ($branch) ]", "bold blue");
+        } elsif ($status =~ /^# Your branch is ahead of '(?:.*?)' by (\d+) commit/m) {
+            print colored( "[ Ahead by $1 ($branch) ]", "bold blue");
         } else {
             print colored( "[ Up-to-date ($branch) ]", "green");
         }

commit ce7538335f3eb09493cdb41fcbbf2eadeeff4c6f
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Sat Oct 17 09:49:28 2009 -0400

    Squelch a warning when you're not on a branch
    
    If you git checkout an unannotated tag, you won't be on a branch

diff --git a/git-sync b/git-sync
index 3156b31..7dbcb6f 100755
--- a/git-sync
+++ b/git-sync
@@ -130,6 +130,7 @@ sub update {
     # Rebase if there are no changes, it is on a tracking
     # branch, and the result would be a fast-forward
     my ($branch) = $status =~ /^# On branch (.*)/m;
+    $branch ||= 'Not currently on any branch';
     if ($status =~ /^# Your branch is behind '.*?' by \d+ commits?, and can be fast-forwarded/m
             and $status =~ /^nothing (?:added )?to commit/m) {
         # git-pull is a shell script, unfortunately, and

commit d3ba93894d9a5a69de5fd96943a168cbdb85e425
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Sat Oct 17 10:27:47 2009 -0400

    into can be set multiple times in a config section

diff --git a/git-sync b/git-sync
index 7dbcb6f..6c276ae 100755
--- a/git-sync
+++ b/git-sync
@@ -60,15 +60,17 @@ for my $name (@categories) {
 
 sub sync_all_local {
     my $name = shift;
-    for my $root (grep {-d} <$sync{$name}{into}/*>) {
-        $root =~ m{/([^/]+)(?:\.git)?$};
-        printf "  %-40s ", $1;
-        if (exists $seen{$root}) {
-            print "\r";
-            next;
+    foreach my $into ( ref $sync{$name}{into} ? @{$sync{$name}{into}} : $sync{$name}{into} ) {
+        for my $root (grep {-d} <$into/*>) {
+            $root =~ m{/([^/]+)(?:\.git)?$};
+            printf "  %-40s ", $1;
+            if (exists $seen{$root}) {
+                print "\r";
+                next;
+            }
+            update($root, 0);
+            $seen{$root} = "";
         }
-        update($root, 0);
-        $seen{$root} = "";
     }
 }
 

commit e46db7470958385f8c7639e4ac588ac55c7bbe15
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Sat Oct 17 10:33:38 2009 -0400

    document how to have a local set of repos

diff --git a/git-sync b/git-sync
index 6c276ae..c1415b2 100755
--- a/git-sync
+++ b/git-sync
@@ -193,3 +193,6 @@ __END__
     path = /git-private
     into = /home/chmrr/work/bps/git
     email = alexmv at bestpractical.com
+[sync "localrepos"]
+    into = /home/chmrr/gitprojects
+    local = true

commit 595d4b6e39eed6c8ebd7a9cdcceaea4ca6e02642
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:04:33 2009 -0400

    Add --verbose argument

diff --git a/git-sync b/git-sync
index c1415b2..aa4a2ad 100755
--- a/git-sync
+++ b/git-sync
@@ -15,6 +15,12 @@ use Git;
 use strict;
 use warnings;
 use Term::ANSIColor;
+use Getopt::Long;
+
+my ($verbose, $pretend);
+GetOptions(
+    verbose => \$verbose,
+);
 
 my %conf = Config::GitLike::Git->new->load;
 
@@ -65,7 +71,7 @@ sub sync_all_local {
             $root =~ m{/([^/]+)(?:\.git)?$};
             printf "  %-40s ", $1;
             if (exists $seen{$root}) {
-                print "\r";
+                print $verbose ? colored("[ Already synchronized ]\n", "dark") : "\r";
                 next;
             }
             update($root, 0);
@@ -89,7 +95,7 @@ sub sync_all_remote {
                 print colored( "[ Already synchronized! ]\n", "red");
                 next;
             } elsif (exists $seen{$root}) {
-                print "\r";
+                print $verbose ? colored("[ Already synchronized ]\n", "dark") : "\r";
                 next;
             }
             $seen{$root} = $name;
@@ -159,20 +165,20 @@ sub update {
     }
 
     # Purge old tracking branches
-    $repo->command( qw/remote prune origin/ ) unless $gitsvn;
+    $repo->command( qw/remote prune origin/ ) unless $gitsvn or $pretend;
 }
 
 sub new {
     my ($root, $name, $reponame, $path) = @_;
     `ssh $sync{$name}{host} [ -e $path/${reponame}.git/config ]`;
     if ($?) {
-        print "\r";
+        print $verbose ? colored("[ Not a git repository ]\n", "dark") : "\r";
         return;
     }
     my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
     chomp $ignore if defined $ignore;
     if (defined $ignore and $ignore eq 'true') {
-        print "\r";
+        print $verbose ? colored("[ sync.ignore set ]\n", "dark") : "\r";
         return;
     }
 

commit 314dca3448f468b3b59c44c3c544b36d81481a89
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:04:55 2009 -0400

    Add --pretend argument, to not actually fetch

diff --git a/git-sync b/git-sync
index aa4a2ad..fbcedc4 100755
--- a/git-sync
+++ b/git-sync
@@ -20,6 +20,7 @@ use Getopt::Long;
 my ($verbose, $pretend);
 GetOptions(
     verbose => \$verbose,
+    pretend => \$pretend,
 );
 
 my %conf = Config::GitLike::Git->new->load;
@@ -122,12 +123,15 @@ sub update {
     if ($gitsvn) {
         print colored( "[ svn ] ", "dark blue" );
          # git-svn doesn't work with $repo->command, hate
-        `git --git-dir @{[$repo->repo_path]} svn fetch -q`;
+        `git --git-dir @{[$repo->repo_path]} svn fetch -q` unless $pretend;
     } else {
-        eval { $repo->command( ["fetch"], STDERR => 0 ); } if 0;
+        eval { $repo->command( ["fetch"], STDERR => 0 ); } unless $pretend;
     }
+
     print colored("[ Fetch failed! $@]\n", "red") and return if $@;
 
+    print colored("[ Fetch ] ", "dark") if $pretend;
+
     print colored("[ Bare repository ]\n", "green") and return if $repo->config_bool('core.bare');
 
     my $status = "";

commit 9fd8b54b557396137b29b67b6c61b5edcb4b1120
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:09:08 2009 -0400

    Whoops -- forgot case where local is behind but dirty, and hence not pulled

diff --git a/git-sync b/git-sync
index fbcedc4..3515f1e 100755
--- a/git-sync
+++ b/git-sync
@@ -157,8 +157,10 @@ sub update {
     } else {
         if ($status =~ /^# Your branch and '.*?' have diverged.*?(\d+) and (\d+) different commit/sm) {
             print colored( "[ Diverged by $1 and $2 commits ($branch) ]", "bold blue" );
-        } elsif ($status =~ /^# Your branch is ahead of '(?:.*?)' by (\d+) commit/m) {
+        } elsif ($status =~ /^# Your branch is ahead of '.*?' by (\d+) commit/m) {
             print colored( "[ Ahead by $1 ($branch) ]", "bold blue");
+        } elsif ($status =~ /^# Your branch is behind '.*?' by (\d+) commit/m) {
+            print colored( "[ Behind by $1 ($branch) ]", "bold blue");
         } else {
             print colored( "[ Up-to-date ($branch) ]", "green");
         }

commit 8ed04d08b7d12179db4384c65e05fdff36b8ad1b
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:16:27 2009 -0400

    --pretend option shouldn't actually call `git pull`

diff --git a/git-sync b/git-sync
index 3515f1e..72b11a5 100755
--- a/git-sync
+++ b/git-sync
@@ -148,10 +148,10 @@ sub update {
         # git-pull is a shell script, unfortunately, and
         # thus can't be run via $repo->command( "pull" )
         chdir($root);
-        print colored( "[ Pulled ($branch) ]\n", "bold green" );
-        my $pull = `git pull --stat`;
+        print colored( $pretend ? "[ Would pull ($branch) ]\n" : "[ Pulled ($branch) ]\n", "bold green" );
+        my $pull = $pretend ? "" : `git pull --stat`;
         # Indent, and colorize (git doesn't, because we're not a tty)
-        $pull =~ s/^/    /gm;
+        $pull =~ s/^/    /gm if length $pull;
         $pull =~ s/^(  .*?)(\+*)(-*)$/$1.colored($2,"green").colored($3,"red")/gme;
         print $pull;
     } else {

commit ba4be5a9d02dcedcc655112ea2e3f74ff2d8e0ed
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:19:34 2009 -0400

    Make --pretend work on new repositories that would be cloned

diff --git a/git-sync b/git-sync
index 72b11a5..166e5b8 100755
--- a/git-sync
+++ b/git-sync
@@ -188,6 +188,8 @@ sub new {
         return;
     }
 
+    print colored("[ Would clone ]\n", "bold green") and return if $pretend;
+
     eval { Git::command( [clone => "$sync{$name}{host}:$path/$reponame", $root], STDERR => 0 ) };
     if ($@) {
         print colored( "[ Clone failed! ]\n", "red");

commit 885dcf7aaa29fa4f756c9560d9e18ce22a23f4d6
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:30:26 2009 -0400

    Cloning fails in void context (!?)

diff --git a/git-sync b/git-sync
index 166e5b8..ab01329 100755
--- a/git-sync
+++ b/git-sync
@@ -190,7 +190,7 @@ sub new {
 
     print colored("[ Would clone ]\n", "bold green") and return if $pretend;
 
-    eval { Git::command( [clone => "$sync{$name}{host}:$path/$reponame", $root], STDERR => 0 ) };
+    my $ret = eval { Git::command( [clone => "$sync{$name}{host}:$path/$reponame", $root], STDERR => 0 ) };
     if ($@) {
         print colored( "[ Clone failed! ]\n", "red");
         return;

commit 279fa342d7a6964b1ad65cb2bd4e4a590fc124a8
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:30:57 2009 -0400

    Remove trailing newline from $@ on fetch failure

diff --git a/git-sync b/git-sync
index ab01329..3945c0e 100755
--- a/git-sync
+++ b/git-sync
@@ -128,7 +128,8 @@ sub update {
         eval { $repo->command( ["fetch"], STDERR => 0 ); } unless $pretend;
     }
 
-    print colored("[ Fetch failed! $@]\n", "red") and return if $@;
+    my $error = $@; chomp $error;
+    print colored("[ Fetch failed! $error]\n", "red") and return if $@;
 
     print colored("[ Fetch ] ", "dark") if $pretend;
 

commit 0754d02e75acab9fe3fcd3b5ccdc3787c92209ab
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 15:32:03 2009 -0400

    Switch to bold red for errors

diff --git a/git-sync b/git-sync
index 3945c0e..10816a9 100755
--- a/git-sync
+++ b/git-sync
@@ -115,7 +115,7 @@ sub update {
     # Already exists, fetch and possibly rebase
     my $repo = eval { Git->repository(Directory => $root) };
     unless ($repo) {
-        print $force ? colored("[ Not a git repository! ]\n", "red") : "\r";
+        print $force ? colored("[ Not a git repository! ]\n", "bold red") : "\r";
         return;
     }
 
@@ -129,7 +129,7 @@ sub update {
     }
 
     my $error = $@; chomp $error;
-    print colored("[ Fetch failed! $error]\n", "red") and return if $@;
+    print colored("[ Fetch failed! $error]\n", "bold red") and return if $@;
 
     print colored("[ Fetch ] ", "dark") if $pretend;
 
@@ -193,7 +193,7 @@ sub new {
 
     my $ret = eval { Git::command( [clone => "$sync{$name}{host}:$path/$reponame", $root], STDERR => 0 ) };
     if ($@) {
-        print colored( "[ Clone failed! ]\n", "red");
+        print colored( "[ Clone failed! ]\n", "bold red");
         return;
     }
     Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )

commit aa447f1835ee15f2343fedad3c6380c8125c8a5d
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 23:41:58 2009 -0400

    Add --dry-run and -v as other options

diff --git a/git-sync b/git-sync
index 10816a9..a31f985 100755
--- a/git-sync
+++ b/git-sync
@@ -19,8 +19,8 @@ use Getopt::Long;
 
 my ($verbose, $pretend);
 GetOptions(
-    verbose => \$verbose,
-    pretend => \$pretend,
+    'verbose|v' => \$verbose,
+    'pretend|dry-run' => \$pretend,
 );
 
 my %conf = Config::GitLike::Git->new->load;

commit 8cc12fb673f3e31d019af1eb6ae5bcb802572539
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 23:47:03 2009 -0400

    Split new() into not being ssh-dependent, just cloning

diff --git a/git-sync b/git-sync
index a31f985..c9f8c00 100755
--- a/git-sync
+++ b/git-sync
@@ -103,7 +103,16 @@ sub sync_all_remote {
             if (-e $root) {
                 update($root, 1);
             } else {
-                new($root => $name => $reponame => $path);
+                `ssh $sync{$name}{host} [ -e $path/${reponame}.git/config ]`;
+                print $verbose ? colored("[ Not a git repository ]\n", "dark") : "\r" and next
+                    if $?;
+
+                my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
+                chomp $ignore if defined $ignore;
+                print $verbose ? colored("[ sync.ignore set ]\n", "dark") : "\r" and next
+                    if defined $ignore and $ignore eq 'true';
+
+                new($root => "$sync{$name}{host}:$path/$reponame", $sync{$name}{email});
             }
         }
     }
@@ -176,28 +185,18 @@ sub update {
 }
 
 sub new {
-    my ($root, $name, $reponame, $path) = @_;
-    `ssh $sync{$name}{host} [ -e $path/${reponame}.git/config ]`;
-    if ($?) {
-        print $verbose ? colored("[ Not a git repository ]\n", "dark") : "\r";
-        return;
-    }
-    my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
-    chomp $ignore if defined $ignore;
-    if (defined $ignore and $ignore eq 'true') {
-        print $verbose ? colored("[ sync.ignore set ]\n", "dark") : "\r";
-        return;
-    }
+    # Path to clone into, path to clone from, user
+    my ($into, $from, $email) = @_;
 
-    print colored("[ Would clone ]\n", "bold green") and return if $pretend;
+    print colored("[ Would clone $from into $into ]\n", "bold green") and return if $pretend;
 
-    my $ret = eval { Git::command( [clone => "$sync{$name}{host}:$path/$reponame", $root], STDERR => 0 ) };
+    my $ret = eval { Git::command( [clone => $from => $into], STDERR => 0 ) };
     if ($@) {
         print colored( "[ Clone failed! ]\n", "bold red");
         return;
     }
-    Git::command( config => "--file", "$root/.git/config", "user.email", $sync{$name}{email} )
-          if $sync{$name}{email};
+    Git::command( config => "--file", "$into/.git/config", "user.email", $email )
+          if $email;
     print colored( "[ Cloned! ]\n", "bold green");
 }
 

commit 10514f8140e6e39b43b777433a296603fd824d96
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 23:52:26 2009 -0400

    Make %sync no longer referenced globally

diff --git a/git-sync b/git-sync
index c9f8c00..b42276a 100755
--- a/git-sync
+++ b/git-sync
@@ -45,29 +45,19 @@ my %seen;
 for my $name (@categories) {
     print colored("Syncing" . (length $name ? " $name" : "")."\n", "bold");
 
-    unless ($sync{$name}{into}) {
+    if (not $sync{$name}{into}) {
         print colored("  No 'into' set, skipping!\n", "red");
-        next;
-    }
-    if (exists $sync{$name}{local}) {
-        sync_all_local($name);
+    } elsif (exists $sync{$name}{local}) {
+        sync_all_local(%{$sync{$name}});
     } else {
-        unless ($sync{$name}{host}) {
-            print colored("  No 'host' set, skipping!\n", "red");
-            next;
-        }
-        unless ($sync{$name}{path}) {
-            print colored("  No 'path' set, skipping!\n", "red");
-            next;
-        }
-        sync_all_remote($name);
+        sync_all_remote(%{$sync{$name}});
     }
     print " "x45,"\n";
 }
 
 sub sync_all_local {
-    my $name = shift;
-    foreach my $into ( ref $sync{$name}{into} ? @{$sync{$name}{into}} : $sync{$name}{into} ) {
+    my %config = @_;
+    foreach my $into ( ref $config{into} ? @{$config{into}} : $config{into} ) {
         for my $root (grep {-d} <$into/*>) {
             $root =~ m{/([^/]+)(?:\.git)?$};
             printf "  %-40s ", $1;
@@ -82,37 +72,47 @@ sub sync_all_local {
 }
 
 sub sync_all_remote {
-    my $name = shift;
-    my @paths = ref $sync{$name}{path} ? @{$sync{$name}{path}} : ($sync{$name}{path});
+    my %config = @_;
+
+    print colored("  No 'host' set, skipping!\n", "red") and return
+        unless $config{host};
+
+    print colored("  No 'path' set, skipping!\n", "red") and return
+        unless $config{path};
+
+    print colored("  Only one value valid for 'into' when 'host' supplied!\n", "red") and return
+        if ref $config{into};
+
+    my @paths = ref $config{path} ? @{$config{path}} : ($config{path});
     for my $path (@paths) {
-        my @list = `ssh $sync{$name}{host} ls $path`;
+        my @list = `ssh $config{host} ls $path`;
         warn("Listing returned ".($? >> 8).", skipping!\n") and next if $?;
         for my $reponame (@list) {
             $reponame =~ s/(\.git)?\n?$//;
-            my $root = "$sync{$name}{into}/$reponame";
+            my $into = "$config{into}/$reponame";
 
             printf "  %-40s ", $reponame;
-            if ($seen{$root}) {
+            if ($seen{$into}) {
                 print colored( "[ Already synchronized! ]\n", "red");
                 next;
-            } elsif (exists $seen{$root}) {
+            } elsif (exists $seen{$into}) {
                 print $verbose ? colored("[ Already synchronized ]\n", "dark") : "\r";
                 next;
             }
-            $seen{$root} = $name;
-            if (-e $root) {
-                update($root, 1);
+            $seen{$into} = $into;
+            if (-e $into) {
+                update($into, 1);
             } else {
-                `ssh $sync{$name}{host} [ -e $path/${reponame}.git/config ]`;
+                `ssh $config{host} [ -e $path/${reponame}.git/config ]`;
                 print $verbose ? colored("[ Not a git repository ]\n", "dark") : "\r" and next
                     if $?;
 
-                my ($ignore) = `ssh $sync{$name}{host} git config --bool -f $path/${reponame}.git/config  sync.ignore`;
+                my ($ignore) = `ssh $config{host} git config --bool -f $path/${reponame}.git/config sync.ignore`;
                 chomp $ignore if defined $ignore;
                 print $verbose ? colored("[ sync.ignore set ]\n", "dark") : "\r" and next
                     if defined $ignore and $ignore eq 'true';
 
-                new($root => "$sync{$name}{host}:$path/$reponame", $sync{$name}{email});
+                new($into => "$config{host}:$path/$reponame", $config{email});
             }
         }
     }

commit 7d9fcfc0dc554634956634c8c11901d37be4b553
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 23:53:27 2009 -0400

    Refactor "already seen this path"

diff --git a/git-sync b/git-sync
index b42276a..507f822 100755
--- a/git-sync
+++ b/git-sync
@@ -61,12 +61,8 @@ sub sync_all_local {
         for my $root (grep {-d} <$into/*>) {
             $root =~ m{/([^/]+)(?:\.git)?$};
             printf "  %-40s ", $1;
-            if (exists $seen{$root}) {
-                print $verbose ? colored("[ Already synchronized ]\n", "dark") : "\r";
-                next;
-            }
+            next if already($root => 0);
             update($root, 0);
-            $seen{$root} = "";
         }
     }
 }
@@ -92,14 +88,7 @@ sub sync_all_remote {
             my $into = "$config{into}/$reponame";
 
             printf "  %-40s ", $reponame;
-            if ($seen{$into}) {
-                print colored( "[ Already synchronized! ]\n", "red");
-                next;
-            } elsif (exists $seen{$into}) {
-                print $verbose ? colored("[ Already synchronized ]\n", "dark") : "\r";
-                next;
-            }
-            $seen{$into} = $into;
+            next if already($into => 1);
             if (-e $into) {
                 update($into, 1);
             } else {
@@ -118,6 +107,19 @@ sub sync_all_remote {
     }
 }
 
+sub already {
+    my ($path, $force) = @_;
+    if ($force and $seen{$path}) {
+        print colored( "[ Already synchronized! ]\n", "red");
+        return 1;
+    } elsif (exists $seen{$path}) {
+        print $verbose ? colored("[ Already synchronized ]\n", "dark") : "\r";
+        return 1;
+    }
+    $seen{$path} = $force;
+    return;
+}
+
 sub update {
     my ($root, $force) = @_;
 

commit e46b1a09d255e660a0358032e21d43455cd02a0d
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 23:54:09 2009 -0400

    Change a warn()ing into a colored print

diff --git a/git-sync b/git-sync
index 507f822..e3d3c11 100755
--- a/git-sync
+++ b/git-sync
@@ -82,7 +82,7 @@ sub sync_all_remote {
     my @paths = ref $config{path} ? @{$config{path}} : ($config{path});
     for my $path (@paths) {
         my @list = `ssh $config{host} ls $path`;
-        warn("Listing returned ".($? >> 8).", skipping!\n") and next if $?;
+        print colored("  Listing returned ".($? >> 8).", skipping!\n", "bold red") and next if $?;
         for my $reponame (@list) {
             $reponame =~ s/(\.git)?\n?$//;
             my $into = "$config{into}/$reponame";

commit 59123d1e1a8c39f21ae9afc0c77d60d8b1571908
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sat Oct 17 23:54:23 2009 -0400

    Github support

diff --git a/git-sync b/git-sync
index e3d3c11..d0ce57c 100755
--- a/git-sync
+++ b/git-sync
@@ -16,6 +16,7 @@ use strict;
 use warnings;
 use Term::ANSIColor;
 use Getopt::Long;
+use LWP::Simple qw();
 
 my ($verbose, $pretend);
 GetOptions(
@@ -49,6 +50,8 @@ for my $name (@categories) {
         print colored("  No 'into' set, skipping!\n", "red");
     } elsif (exists $sync{$name}{local}) {
         sync_all_local(%{$sync{$name}});
+    } elsif (exists $sync{$name}{github}) {
+        sync_all_github(%{$sync{$name}});
     } else {
         sync_all_remote(%{$sync{$name}});
     }
@@ -67,6 +70,41 @@ sub sync_all_local {
     }
 }
 
+sub sync_all_github {
+    my %config = @_;
+
+    print colored("  Only one value valid for 'into' when 'guthub' supplied", "red") and return
+        if ref $config{into};
+
+    my $decoder = eval { require JSON::Any; JSON::Any->import; JSON::Any->new };
+    print colored("  GitHub sync support requires the JSON::Any module\n", "red") and return
+        if $@ or not $decoder;
+
+    my @accounts = ref $config{github} ? @{$config{github}} : ($config{github});
+    for my $acct (@accounts) {
+        my $content = LWP::Simple::get("http://github.com/api/v1/json/$acct");
+        print colored("GET of http://github.com/api/v1/json/$acct failed!\n", "bold red") and return
+            unless defined $content;
+
+        my $data = eval {$decoder->jsonToObj($content)};
+        print colored("Parsing of GitHub JSON response failed! $@\n", "bold red")."\n$content\n" and return
+            unless defined $data;
+
+        for my $repo (@{$data->{user}{repositories} || []}) {
+            my $reponame = $repo->{name};
+            my $root = "$config{into}/$reponame";
+
+            printf "  %-40s ", $reponame;
+            next if already($root => 1);
+            if (-e $root) {
+                update($root, 1);
+            } else {
+                new($root => "git\@github.com:$acct/$reponame.git" => $config{email});
+            }
+        }
+    }
+}
+
 sub sync_all_remote {
     my %config = @_;
 

commit 4deb40589848d22e055d08612d420fcbef7220db
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Oct 18 00:33:34 2009 -0400

    Clones from github mysteriously fail without clone -q
    
    Without the -q, repositories are cloned from github, but are left in
    inconsistent state, claiming:
    
        error: bad signature
        fatal: index file corrupt
    
    Git.pm is a sad, sad piece of business.

diff --git a/git-sync b/git-sync
index d0ce57c..f443a8a 100755
--- a/git-sync
+++ b/git-sync
@@ -230,7 +230,7 @@ sub new {
 
     print colored("[ Would clone $from into $into ]\n", "bold green") and return if $pretend;
 
-    my $ret = eval { Git::command( [clone => $from => $into], STDERR => 0 ) };
+    my $ret = eval { Git::command( [clone => "-q" => $from => $into], STDERR => 0 ) };
     if ($@) {
         print colored( "[ Clone failed! ]\n", "bold red");
         return;

commit 2b3f7d3f2caba8bd58943992a7fd1e763d7a2ff4
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Oct 18 00:36:16 2009 -0400

    Add github example

diff --git a/git-sync b/git-sync
index f443a8a..414ab62 100755
--- a/git-sync
+++ b/git-sync
@@ -250,3 +250,6 @@ __END__
 [sync "localrepos"]
     into = /home/chmrr/gitprojects
     local = true
+[sync "github"]
+    into = /home/chmrr/github
+    github = alexmv

commit abd5dac38563a8a84f1b95fd7653a91b8d451e9d
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Oct 18 00:39:17 2009 -0400

    Consistent indentation on error messages

diff --git a/git-sync b/git-sync
index 414ab62..0153b3b 100755
--- a/git-sync
+++ b/git-sync
@@ -83,11 +83,11 @@ sub sync_all_github {
     my @accounts = ref $config{github} ? @{$config{github}} : ($config{github});
     for my $acct (@accounts) {
         my $content = LWP::Simple::get("http://github.com/api/v1/json/$acct");
-        print colored("GET of http://github.com/api/v1/json/$acct failed!\n", "bold red") and return
+        print colored("  GET of http://github.com/api/v1/json/$acct failed!\n", "bold red") and next
             unless defined $content;
 
         my $data = eval {$decoder->jsonToObj($content)};
-        print colored("Parsing of GitHub JSON response failed! $@\n", "bold red")."\n$content\n" and return
+        print colored("  Parsing of GitHub JSON response failed! $@\n", "bold red")."\n$content\n" and next
             unless defined $data;
 
         for my $repo (@{$data->{user}{repositories} || []}) {

commit 24d13afd79710e21772debd454f3137ac1f44756
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Oct 18 00:40:31 2009 -0400

    Fix typo in error message

diff --git a/git-sync b/git-sync
index 0153b3b..23efd22 100755
--- a/git-sync
+++ b/git-sync
@@ -73,7 +73,7 @@ sub sync_all_local {
 sub sync_all_github {
     my %config = @_;
 
-    print colored("  Only one value valid for 'into' when 'guthub' supplied", "red") and return
+    print colored("  Only one value valid for 'into' when 'github' supplied", "red") and return
         if ref $config{into};
 
     my $decoder = eval { require JSON::Any; JSON::Any->import; JSON::Any->new };

commit 766f06d02f1cecc51c7ae8746022f2cd9c03112a
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Oct 18 01:01:37 2009 -0400

    Add a --logs option to add output of `git log --oneline`

diff --git a/git-sync b/git-sync
index 23efd22..59161a1 100755
--- a/git-sync
+++ b/git-sync
@@ -18,10 +18,11 @@ use Term::ANSIColor;
 use Getopt::Long;
 use LWP::Simple qw();
 
-my ($verbose, $pretend);
+my ($verbose, $pretend, $log);
 GetOptions(
     'verbose|v' => \$verbose,
     'pretend|dry-run' => \$pretend,
+    'log|l' => \$log,
 );
 
 my %conf = Config::GitLike::Git->new->load;
@@ -193,31 +194,45 @@ sub update {
     # branch, and the result would be a fast-forward
     my ($branch) = $status =~ /^# On branch (.*)/m;
     $branch ||= 'Not currently on any branch';
-    if ($status =~ /^# Your branch is behind '.*?' by \d+ commits?, and can be fast-forwarded/m
-            and $status =~ /^nothing (?:added )?to commit/m) {
+    if ($status =~ /^nothing (?:added )?to commit/m
+            and $status =~ /^# Your branch is behind '(.*?)' by (\d+) commits?, and can be fast-forwarded/m) {
+        my ($tracking, $behind) = ($1, $2);
         # git-pull is a shell script, unfortunately, and
         # thus can't be run via $repo->command( "pull" )
         chdir($root);
-        print colored( $pretend ? "[ Would pull ($branch) ]\n" : "[ Pulled ($branch) ]\n", "bold green" );
+        print colored( $pretend ?
+                           "[ Would pull $behind commits ($branch) ]\n" :
+                           "[ Pulled $behind commits ($branch) ]\n",
+                       "bold green" );
+
+        print logs($repo, $branch => $tracking);
+
         my $pull = $pretend ? "" : `git pull --stat`;
+        # This line will always be present, and is content-free
+        $pull =~ s/^First, rewinding head.*?\n//m;
         # Indent, and colorize (git doesn't, because we're not a tty)
+        $pull =~ s/^( .*?)(\+*)(-*)$/$1.colored($2,"green").colored($3,"red")/gme;
         $pull =~ s/^/    /gm if length $pull;
-        $pull =~ s/^(  .*?)(\+*)(-*)$/$1.colored($2,"green").colored($3,"red")/gme;
         print $pull;
     } else {
+        my $logs = "";
         if ($status =~ /^# Your branch and '.*?' have diverged.*?(\d+) and (\d+) different commit/sm) {
             print colored( "[ Diverged by $1 and $2 commits ($branch) ]", "bold blue" );
-        } elsif ($status =~ /^# Your branch is ahead of '.*?' by (\d+) commit/m) {
-            print colored( "[ Ahead by $1 ($branch) ]", "bold blue");
-        } elsif ($status =~ /^# Your branch is behind '.*?' by (\d+) commit/m) {
-            print colored( "[ Behind by $1 ($branch) ]", "bold blue");
+        } elsif ($status =~ /^# Your branch is ahead of '(.*?)' by (\d+) commit/m) {
+            my ($tracking, $ahead) = ($1, $2);
+            print colored( "[ Ahead by $ahead ($branch) ]", "bold blue");
+            $logs = logs($repo, $tracking => $branch);
+        } elsif ($status =~ /^# Your branch is behind '(.*?)' by (\d+) commit/m) {
+            my ($tracking, $behind) = ($1, $2);
+            print colored( "[ Behind by $behind ($branch) ]", "bold blue");
+            $logs = logs($repo, $branch => $tracking);
         } else {
             print colored( "[ Up-to-date ($branch) ]", "green");
         }
         if ($status !~ /^nothing (?:added )?to commit/m) {
             print colored( " [ Dirty ]", "yellow");
         }
-        print "\n";
+        print "\n$logs";
     }
 
     # Purge old tracking branches
@@ -240,6 +255,15 @@ sub new {
     print colored( "[ Cloned! ]\n", "bold green");
 }
 
+sub logs {
+    my ($repo, $from, $to) = @_;
+    return "" unless $log;
+    my $logmsg = $repo->command( log => "--oneline", "--reverse", "$from..$to" );
+    # Re-colorize and indent
+    $logmsg =~ s/^(\S+)/"    ".colored($1,"yellow")/egm;
+    return $logmsg;
+}
+
 __END__
 [sync "bps"]
     host = fsck.com

commit 4c5330f3b3bdfcef2d1b5b0e830ebefa9f9c3191
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Sun Oct 18 19:04:37 2009 -0400

    Use different colors for ahead, behind, and diverged

diff --git a/git-sync b/git-sync
index 59161a1..c3b1f2c 100755
--- a/git-sync
+++ b/git-sync
@@ -217,14 +217,14 @@ sub update {
     } else {
         my $logs = "";
         if ($status =~ /^# Your branch and '.*?' have diverged.*?(\d+) and (\d+) different commit/sm) {
-            print colored( "[ Diverged by $1 and $2 commits ($branch) ]", "bold blue" );
+            print colored( "[ Diverged by $1 and $2 commits ($branch) ]", "bold cyan" );
         } elsif ($status =~ /^# Your branch is ahead of '(.*?)' by (\d+) commit/m) {
             my ($tracking, $ahead) = ($1, $2);
             print colored( "[ Ahead by $ahead ($branch) ]", "bold blue");
             $logs = logs($repo, $tracking => $branch);
         } elsif ($status =~ /^# Your branch is behind '(.*?)' by (\d+) commit/m) {
             my ($tracking, $behind) = ($1, $2);
-            print colored( "[ Behind by $behind ($branch) ]", "bold blue");
+            print colored( "[ Behind by $behind ($branch) ]", "bold magenta");
             $logs = logs($repo, $branch => $tracking);
         } else {
             print colored( "[ Up-to-date ($branch) ]", "green");

commit c09a8c304e976248db439b61e73f1e40f45ab059
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Mon Oct 19 00:37:33 2009 -0400

    Propagate signals (like SIGINT) from Git::command and `` back to ourselves

diff --git a/git-sync b/git-sync
index c3b1f2c..d5acfca 100755
--- a/git-sync
+++ b/git-sync
@@ -18,6 +18,11 @@ use Term::ANSIColor;
 use Getopt::Long;
 use LWP::Simple qw();
 
+$SIG{INT} = sub {
+    print colored("\n\nInterrupted!\n", "bold red");
+    exit;
+};
+
 my ($verbose, $pretend, $log);
 GetOptions(
     'verbose|v' => \$verbose,
@@ -177,6 +182,7 @@ sub update {
     } else {
         eval { $repo->command( ["fetch"], STDERR => 0 ); } unless $pretend;
     }
+    kill $? & 127, $$ if $? & 127;
 
     my $error = $@; chomp $error;
     print colored("[ Fetch failed! $error]\n", "bold red") and return if $@;
@@ -208,6 +214,8 @@ sub update {
         print logs($repo, $branch => $tracking);
 
         my $pull = $pretend ? "" : `git pull --stat`;
+        kill $? & 127, $$ if $? & 127;
+
         # This line will always be present, and is content-free
         $pull =~ s/^First, rewinding head.*?\n//m;
         # Indent, and colorize (git doesn't, because we're not a tty)
@@ -237,6 +245,7 @@ sub update {
 
     # Purge old tracking branches
     $repo->command( qw/remote prune origin/ ) unless $gitsvn or $pretend;
+    kill $? & 127, $$ if $? & 127;
 }
 
 sub new {
@@ -250,6 +259,8 @@ sub new {
         print colored( "[ Clone failed! ]\n", "bold red");
         return;
     }
+    kill $? & 127, $$ if $? & 127;
+
     Git::command( config => "--file", "$into/.git/config", "user.email", $email )
           if $email;
     print colored( "[ Cloned! ]\n", "bold green");

commit 73952e2eebf3028d87a68b54103dbe83e1fb03c2
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Oct 30 15:37:58 2009 -0400

    Create the 'into' directory if it doesn't exist

diff --git a/git-sync b/git-sync
index d5acfca..f372963 100755
--- a/git-sync
+++ b/git-sync
@@ -67,6 +67,10 @@ for my $name (@categories) {
 sub sync_all_local {
     my %config = @_;
     foreach my $into ( ref $config{into} ? @{$config{into}} : $config{into} ) {
+        unless (-d $into) {
+            print colored("  Directory '$into' does not exist!\n", "bold red");
+            next;
+        }
         for my $root (grep {-d} <$into/*>) {
             $root =~ m{/([^/]+)(?:\.git)?$};
             printf "  %-40s ", $1;
@@ -82,6 +86,12 @@ sub sync_all_github {
     print colored("  Only one value valid for 'into' when 'github' supplied", "red") and return
         if ref $config{into};
 
+    unless (-d $config{into}) {
+        print colored("  Creating directory '$config{into}'\n", "bold");
+        print colored("  Directory creation failed: $!\n", "bold red") and return
+            unless mkdir $config{into};
+    }
+
     my $decoder = eval { require JSON::Any; JSON::Any->import; JSON::Any->new };
     print colored("  GitHub sync support requires the JSON::Any module\n", "red") and return
         if $@ or not $decoder;
@@ -123,6 +133,12 @@ sub sync_all_remote {
     print colored("  Only one value valid for 'into' when 'host' supplied!\n", "red") and return
         if ref $config{into};
 
+    unless (-d $config{into}) {
+        print colored("  Creating directory '$config{into}'\n", "bold");
+        print colored("  Directory creation failed: $!\n", "bold red") and return
+            unless mkdir $config{into};
+    }
+
     my @paths = ref $config{path} ? @{$config{path}} : ($config{path});
     for my $path (@paths) {
         my @list = `ssh $config{host} ls $path`;

commit 9da5111cb94e7af084b0390f0017f6fedc34731f
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Oct 30 16:38:39 2009 -0400

    Use File::Path::mkpath instead of mkdir, for when `mkdir -p`-like effects are wanted

diff --git a/git-sync b/git-sync
index f372963..0fb3261 100755
--- a/git-sync
+++ b/git-sync
@@ -17,6 +17,7 @@ use warnings;
 use Term::ANSIColor;
 use Getopt::Long;
 use LWP::Simple qw();
+use File::Path qw();
 
 $SIG{INT} = sub {
     print colored("\n\nInterrupted!\n", "bold red");
@@ -89,7 +90,7 @@ sub sync_all_github {
     unless (-d $config{into}) {
         print colored("  Creating directory '$config{into}'\n", "bold");
         print colored("  Directory creation failed: $!\n", "bold red") and return
-            unless mkdir $config{into};
+            unless eval { File::Path::mkpath($config{into}) };
     }
 
     my $decoder = eval { require JSON::Any; JSON::Any->import; JSON::Any->new };
@@ -136,7 +137,7 @@ sub sync_all_remote {
     unless (-d $config{into}) {
         print colored("  Creating directory '$config{into}'\n", "bold");
         print colored("  Directory creation failed: $!\n", "bold red") and return
-            unless mkdir $config{into};
+            unless eval { File::Path::mkpath($config{into}) };
     }
 
     my @paths = ref $config{path} ? @{$config{path}} : ($config{path});

commit 8bf9e5d5ec7c26432462e37ba7ab47f520a04558
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Fri Oct 30 19:26:47 2009 -0400

    use remote update rather than fetch
    
    If you have multiple remotes, git fetch silently does nothing.
    Unfortunately, git remote update run from Git::command fails
    in void context with return code 13?

diff --git a/git-sync b/git-sync
index 0fb3261..a01c165 100755
--- a/git-sync
+++ b/git-sync
@@ -197,7 +197,7 @@ sub update {
          # git-svn doesn't work with $repo->command, hate
         `git --git-dir @{[$repo->repo_path]} svn fetch -q` unless $pretend;
     } else {
-        eval { $repo->command( ["fetch"], STDERR => 0 ); } unless $pretend;
+        my $ret = eval { $repo->command( qw/remote update/ ); } unless $pretend;
     }
     kill $? & 127, $$ if $? & 127;
 

commit c1e8123a27c728238ffd5522799c93c40abb4df2
Author: Kevin Falcone <falcone at bestpractical.com>
Date:   Wed Nov 4 10:15:41 2009 -0500

    Prune while Updating
    
    This makes sure we prune all your hedges, rather than just origin

diff --git a/git-sync b/git-sync
index a01c165..891f024 100755
--- a/git-sync
+++ b/git-sync
@@ -197,7 +197,7 @@ sub update {
          # git-svn doesn't work with $repo->command, hate
         `git --git-dir @{[$repo->repo_path]} svn fetch -q` unless $pretend;
     } else {
-        my $ret = eval { $repo->command( qw/remote update/ ); } unless $pretend;
+        my $ret = eval { $repo->command( qw/remote update --prune/ ); } unless $pretend;
     }
     kill $? & 127, $$ if $? & 127;
 
@@ -260,9 +260,6 @@ sub update {
         print "\n$logs";
     }
 
-    # Purge old tracking branches
-    $repo->command( qw/remote prune origin/ ) unless $gitsvn or $pretend;
-    kill $? & 127, $$ if $? & 127;
 }
 
 sub new {

commit ce8e6164f47ec942425ea610bb2dbede1d1dd15f
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Wed Nov 4 17:57:00 2009 -0500

    Localize $? when it gets set

diff --git a/git-sync b/git-sync
index 891f024..cb24957 100755
--- a/git-sync
+++ b/git-sync
@@ -265,6 +265,7 @@ sub update {
 sub new {
     # Path to clone into, path to clone from, user
     my ($into, $from, $email) = @_;
+    local $?;
 
     print colored("[ Would clone $from into $into ]\n", "bold green") and return if $pretend;
 

commit ae7281dfd903beb1a3f00447c52fa5f76ba70822
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Wed Nov 4 17:58:01 2009 -0500

    Show clone error if verbose is set

diff --git a/git-sync b/git-sync
index cb24957..72e6b60 100755
--- a/git-sync
+++ b/git-sync
@@ -272,6 +272,7 @@ sub new {
     my $ret = eval { Git::command( [clone => "-q" => $from => $into], STDERR => 0 ) };
     if ($@) {
         print colored( "[ Clone failed! ]\n", "bold red");
+        print colored( "Error: $@\n", "red") if ($verbose);
         return;
     }
     kill $? & 127, $$ if $? & 127;

commit 4273ad2c115a8f45670e70ef01509698fc120c77
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Wed Nov 4 18:18:09 2009 -0500

    Make new() have a true return value on success

diff --git a/git-sync b/git-sync
index 72e6b60..5c09a22 100755
--- a/git-sync
+++ b/git-sync
@@ -267,19 +267,20 @@ sub new {
     my ($into, $from, $email) = @_;
     local $?;
 
-    print colored("[ Would clone $from into $into ]\n", "bold green") and return if $pretend;
+    print colored("[ Would clone $from into $into ]\n", "bold green") and return 1 if $pretend;
 
     my $ret = eval { Git::command( [clone => "-q" => $from => $into], STDERR => 0 ) };
     if ($@) {
         print colored( "[ Clone failed! ]\n", "bold red");
         print colored( "Error: $@\n", "red") if ($verbose);
-        return;
+        return undef;
     }
     kill $? & 127, $$ if $? & 127;
 
     Git::command( config => "--file", "$into/.git/config", "user.email", $email )
           if $email;
     print colored( "[ Cloned! ]\n", "bold green");
+    return 1;
 }
 
 sub logs {

commit 3263bd94a7df0abeaad95d0753606b0b477ad507
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Wed Nov 4 18:18:48 2009 -0500

    Make github clones fall back to unauth

diff --git a/git-sync b/git-sync
index 5c09a22..1237ec8 100755
--- a/git-sync
+++ b/git-sync
@@ -116,7 +116,11 @@ sub sync_all_github {
             if (-e $root) {
                 update($root, 1);
             } else {
-                new($root => "git\@github.com:$acct/$reponame.git" => $config{email});
+                my $auth = new($root => "git\@github.com:$acct/$reponame.git" => $config{email});
+                unless ($auth) {
+                    printf "  %-40s ", "...trying again, anonymously";
+                    new($root => "git://github.com/$acct/$reponame.git" => $config{email});
+                }
             }
         }
     }

commit 784b144a03a0246a1a9c2832e90c8fc5b7766e57
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Fri Nov 6 13:11:01 2009 -0500

    Add back STDERR => 0 so output isn't marred with "Unpacking objects" from fetch

diff --git a/git-sync b/git-sync
index 1237ec8..4a2cba9 100755
--- a/git-sync
+++ b/git-sync
@@ -201,7 +201,7 @@ sub update {
          # git-svn doesn't work with $repo->command, hate
         `git --git-dir @{[$repo->repo_path]} svn fetch -q` unless $pretend;
     } else {
-        my $ret = eval { $repo->command( qw/remote update --prune/ ); } unless $pretend;
+        my $ret = eval { $repo->command( [qw/remote update --prune/], STDERR => 0 ); } unless $pretend;
     }
     kill $? & 127, $$ if $? & 127;
 

-----------------------------------------------------------------------



More information about the Bps-public-commit mailing list