Subject: [PATCH] git-remote exclude

From: Quy Tonthat <[email-masked]>
Date: Mon, 15 Jan 2007 01:57:26 +1100

"git-remote exclude" can be used to prevent one or more unwanted remote branches
from being tracked. After, for example,
    $ git-remote origin exclude man html
"git-fetch origin" will no longer fetch origin/man and origin/html.

"git-remote exclude" does not check whether the "unwanted" branch
really exists on the remote repo.

Signed-off-by: Quy Tonthat <[email-masked]>
---
 git-remote.perl |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/git-remote.perl b/git-remote.perl
index fc055b6..8ee1bea 100755
--- a/git-remote.perl
+++ b/git-remote.perl
@@ -243,6 +243,47 @@ sub add_remote {
 		      "+refs/heads/*:refs/remotes/$name/*");
 }
 
+sub exclude_remote_branch {
+	my ($name, @branches) = @_;
+	if (!exists $remote->{$name}) {
+		print STDERR "remote $name does not exists.\n";
+		exit(1);
+	}
+
+	my $wildcard = "";
+	my %fetch_entries = ();
+	my @fetches = $git->command(qw(repo-config --get-all), "remote.$name.fetch");
+	foreach $fetch (@fetches) {
+		if ($fetch =~ m%^\+?refs/heads/\*:refs/remotes/$name/\*$%) {
+			$wildcard = $fetch;
+		}
+		else {
+			foreach $br (@branches) {
+				if ($fetch =~ m#^refs/heads/$br:.*$#) {
+					$fetch_entries{$br} = $fetch;
+				}
+			}
+		}
+	}
+
+	if (!$wildcard) {
+		print STDERR "No wildcard entry for $name. Config not changed\n";
+		exit(1);
+	}
+	my $clean;
+       	($clean = $wildcard) =~ s/([+*])/\\$1/g;
+	$git->command(qw(repo-config --unset), "remote.$name.fetch", $clean);
+	foreach $key (keys %fetch_entries) {
+		$git->command(qw(repo-config --unset), "remote.$name.fetch",
+				$fetch_entries{$key});
+	}
+	foreach $br (@branches) {
+		$git->command(qw(repo-config --add), "remote.$name.fetch",
+			"refs/heads/$br:");
+	}
+	$git->command(qw(repo-config --add), "remote.$name.fetch", $wildcard);
+}
+
 if (!@ARGV) {
 	for (sort keys %$remote) {
 		print "$_\n";
@@ -274,9 +315,19 @@ elsif ($ARGV[0] eq 'add') {
 	}
 	add_remote($ARGV[1], $ARGV[2]);
 }
+elsif ($ARGV[0] eq 'exclude') {
+	if (@ARGV < 3) {
+		print STDERR "Usage: git remote exclude <name> <branch>...\n";
+		exit(1);
+	}
+	my @branches = @ARGV;
+	shift(@branches); shift(@branches);
+	exclude_remote_branch($ARGV[1], @branches);
+}
 else {
 	print STDERR "Usage: git remote\n";
 	print STDERR "       git remote add <name> <url>\n";
+	print STDERR "       git remote exclude <name> <branch>...\n";
 	print STDERR "       git remote show <name>\n";
 	exit(1);
 }