From 801eba7a6e58c1e740056722244120459ea8c7bf Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Mon, 18 Jan 2010 13:37:57 +0100 Subject: [PATCH] git-split-repository --- git-filter-index | 121 ++++++++++++++++++++++++++++++++++++++++++ git-filter-repository | 11 ++++ git-pullall | 2 +- git-split-repository | 46 ++++++++++++++++ 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100755 git-filter-index create mode 100755 git-filter-repository create mode 100755 git-split-repository diff --git a/git-filter-index b/git-filter-index new file mode 100755 index 0000000..18ab48b --- /dev/null +++ b/git-filter-index @@ -0,0 +1,121 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +my @filters = (); +for(@ARGV) +{ + if(/^ + (?[-+]) + s + (?.) + (?.*?) + \k + (?.*) + \k + $/sx) + { + push @filters, { + search => $+{search}, + replace => $+{replace}, + want => $+{want} eq '+' + }; + } + elsif(/^ + (?[-+]) + (?: + m + (?.) + | + (?\/) + ) + (?.*?) + \k + $/sx) + { + push @filters, { + search => $+{search}, + replace => undef, + want => $+{want} eq '+' + }; + } + elsif(/^ + (?[-+]) + $/sx) + { + push @filters, { + search => '^', + replace => undef, + want => $+{want} eq '+' + }; + } + else + { + die "Usage: $0 filterexpression filterexpression..., where a filter expression is of the form +s/search/replace/, +m/search/, +, -s/search/replace/, -m/search/, -"; + } +} + +sub fillin($@) +{ + my ($str, @args) = @_; + $str =~ s{\\([1-9])|(\&)|(\\)\\}{ + $1 ? $args[$1] : $2 ? $args[0] : $3 + }ge; + return $str; +} + +my $current_output = $ENV{output}; +sub filter($) +{ + my ($s) = @_; + for(@filters) + { + my ($search, $replace, $want) = ($_->{search}, $_->{replace}, $_->{want}); + my $fn = $s; + if($fn =~ s/$search/defined $replace ? fillin $replace, $&, map { substr($s, $-[$_], $+[$_] - $-[$_]) } 0..(@+ - 1) : $&/se) + { + $fn = $s unless $want; + return ($fn, $want); + } + } + # nothing matched + return ($s, 0); +} + +open my $infh, '-|', 'git', 'ls-files', '-s'; +my $idx = ""; +my $plus = 0; +my $minus = 0; +while(<$infh>) +{ + chomp; + /^(\d+) ([0-9a-f]+) (\d+)\t(.*)$/ or die "invalid index line: $_"; + my ($mode, $hash, $stageno, $filename) = ($1, $2, $3, $4); + my ($filename_new, $want) = filter($filename); + if($want) + { + $idx .= "0 0000000000000000000000000000000000000000 $stageno\t$filename\n" + if $filename ne $filename_new; + $idx .= "$mode $hash $stageno\t$filename_new\n"; + ++$plus; + } + else + { + $idx .= "0 0000000000000000000000000000000000000000 $stageno\t$filename\n"; + ++$minus; + } +} +close $infh + or die "git-ls-files: $!"; + +print "$plus:$minus\n"; + +open my $outfh, ">", "/tmp/idxtest"; +print $outfh $idx; +close $outfh; + +open my $outfh, '|-', 'git', 'update-index', '--index-info'; +print $outfh $idx; +close $outfh + or die "git-update-index: $!"; diff --git a/git-filter-repository b/git-filter-repository new file mode 100755 index 0000000..2e088d0 --- /dev/null +++ b/git-filter-repository @@ -0,0 +1,11 @@ +#!/bin/sh + +# expects a filter file of syntax like filter-index + +export filterfile="$1" +git filter-branch --remap-to-ancestor --prune-empty --index-filter ' + xargs -0r git filter-index < "$filterfile" +' -- --all +git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 -r git update-ref -d || true +git reflog expire --expire=now --all +git gc --prune=now --aggressive diff --git a/git-pullall b/git-pullall index c54032c..c29d940 100755 --- a/git-pullall +++ b/git-pullall @@ -27,7 +27,7 @@ eval `git for-each-ref --shell --format=' b=${b#refs/heads/}; if git config branch.$b.merge >/dev/null && git config branch.$b.remote >/dev/null; then git checkout "$b"; - git pull; + git pull || true; fi; ' refs/heads/` git checkout "$cur" diff --git a/git-split-repository b/git-split-repository new file mode 100755 index 0000000..0ea0899 --- /dev/null +++ b/git-split-repository @@ -0,0 +1,46 @@ +#!/bin/sh + +set -ex + +d="$PWD" +src=$1 +shift + +# expects command line options like +# bspfiles='s,^data/(?=.*(?:\.bsp|/lm_.*\.tga)$),,' \ +# a_nonbsp= +# i.e. like filter-index, but with reponame= instead of . + +repos=`for x in "$@"; do + case "$x" in + delete=*) + ;; + *=*) + echo "${x%%=*}" + ;; + esac +done | sort -u` + +export filterfile=`mktemp` + +for r in $repos; do + rsync -vaSHP --delete "$src" "$r.git/" + cd "$r.git" + for x in "$@"; do + case "$x" in + *=*) + rr=${x%%=*} + f=${x#*=} + if [ x"$r" = x"$rr" ]; then + printf -- "+%s\0" "$f" + else + printf -- "-%s\0" "$f" + fi + ;; + esac + done >"$filterfile" + git filter-repository "$filterfile" + cd "$d" +done + +rm -f "$filterfile" -- 2.39.2