aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--NEWS3
-rw-r--r--build.macros.in9
-rwxr-xr-xgit-repository--after-tarball63
-rwxr-xr-xgit-repository--apply-patch158
5 files changed, 235 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index cc728de..5f6fbcb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -28,6 +28,8 @@ pkg_scripts = \
filter.sh \
find-lang.pl \
find-debuginfo.sh \
+ git-repository--after-tarball \
+ git-repository--apply-patch \
http.req \
magic.prov \
magic.req \
diff --git a/NEWS b/NEWS
index 41e9eba..c3fb925 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,6 @@
+- when %_with_git_repository is set, define %_after_setup and %_patch to use
+ the new scripts git-repository--after-tarball and git-repository--apply-patch
+
Version 1.88 - 7 January 2009, by Christophe Fergeau
- fix ugly warning during invocation of php.req
diff --git a/build.macros.in b/build.macros.in
index 9ce5d86..15bfa83 100644
--- a/build.macros.in
+++ b/build.macros.in
@@ -7,6 +7,15 @@
# [Pixel, Dec 2008] deprecated, to remove as soon as rpm 4.6.0 dust settles down
%defaultbuildroot %{_tmppath}/%{name}-%{version}-%{release}-buildroot
+
+# when %_with_git_repository is set, these macros modify the behaviour of "%prep" step:
+%_after_setup %{?_with_git_repository:GIT_URL="%{?git_url}" GIT_REPOSITORY_CACHE=%{?git_repository_cache} @RPMVENDORDIR@/git-repository--after-tarball}
+%_patch %{?_with_git_repository:PKG_NAME=%{name} @RPMVENDORDIR@/git-repository--apply-patch}%{?!_with_git_repository:%__patch}
+
+# used by "git-repository--after-tarball":
+%git_repository_cache %_topdir/%{name}.git
+
+
# Various programs used in rpm scripts
%_update_desktop_database_bin %{_bindir}/update-desktop-database
%_update_mime_database_bin %{_bindir}/update-mime-database
diff --git a/git-repository--after-tarball b/git-repository--after-tarball
new file mode 100755
index 0000000..5fda909
--- /dev/null
+++ b/git-repository--after-tarball
@@ -0,0 +1,63 @@
+#!/bin/sh -ex
+
+# usage: git-repository--after-tarball [<tarballs>]
+# with optional environment variables:
+# - GIT_URL="git://xxx/foo.git [branch]"
+# - GIT_REPOSITORY_CACHE=/zzz/foo.git
+#
+# the GIT_REPOSITORY_CACHE can be used with or without GIT_URL
+# - if GIT_URL is given, GIT_REPOSITORY_CACHE will be a "bare" clone of GIT_URL
+# - otherwise, GIT_REPOSITORY_CACHE can be created using:
+# % git clone --bare BUILD/foo-1 $GIT_REPOSITORY_CACHE
+# where foo-1 is the previous version
+
+
+tarballs="$*"
+
+
+git_clone_in_cwd() {
+ URL=$1
+ [ -n "$2" ] && BRANCH="origin/$2"
+
+ git clone $URL .git-tmp
+
+ cd .git-tmp
+ git checkout $BRANCH
+ cd ..
+
+ mv .git-tmp/.git .
+ rm -r .git-tmp
+}
+
+our_git_clone() {
+ URL=$1
+ HEAD=$2
+
+ if [ -n "$GIT_REPOSITORY_CACHE" ]; then
+ if [ -d "$GIT_REPOSITORY_CACHE" ]; then
+ cd "$GIT_REPOSITORY_CACHE"
+ git fetch $GIT_URL
+ cd -
+ else
+ git clone --bare $URL "$GIT_REPOSITORY_CACHE"
+ fi
+ git_clone_in_cwd "$GIT_REPOSITORY_CACHE" $HEAD
+ else
+ git_clone_in_cwd $URL $HEAD
+ fi
+}
+
+if [ ! -e .git ]; then
+ if [ -n "$GIT_URL" ]; then
+ our_git_clone $GIT_URL
+ elif [ -n "$GIT_REPOSITORY_CACHE" -a -d "$GIT_REPOSITORY_CACHE" ]; then
+ git_clone_in_cwd "$GIT_REPOSITORY_CACHE" vanilla
+ else
+ git init
+ fi
+fi
+git add .
+git commit -q -a -m "imported $tarballs"
+git branch -f vanilla
+git branch -f patches-applied
+git checkout patches-applied
diff --git a/git-repository--apply-patch b/git-repository--apply-patch
new file mode 100755
index 0000000..a4bdf8b
--- /dev/null
+++ b/git-repository--apply-patch
@@ -0,0 +1,158 @@
+#!/usr/bin/perl
+
+# this script can be used instead of "/usr/bin/patch [options] -i xxx.patch"
+
+
+use strict;
+use warnings;
+
+my @argv = @ARGV;
+my $verbose;
+
+my @patches;
+while ($argv[-1] =~ /\.(patch|diff)$/) {
+ unshift @patches, pop @argv;
+}
+
+@patches or die "git-repository--apply-patch can not work with compressed patches\n"; # happens when the patch is passed through stdin
+
+my @opts;
+while (@argv) {
+ my $s = shift @argv;
+ if ($s eq '-b') {
+ # we don't want .xxx files
+ } elsif ($s eq '--suffix') {
+ # we don't want .xxx files
+ shift @argv;
+ } elsif ($s eq '-i') {
+ # ignore "-i"
+ } else {
+ push @opts, $s;
+ }
+}
+
+# we really don't want .orig when using git (even when there are hunks)
+push @opts, '--no-backup-if-mismatch';
+
+foreach my $patch_file (@patches) {
+ my @header = get_patch_header($patch_file);
+
+ if (grep { /^Subject:/ } @header) {
+ my $patch_file_ = fix_git_patch($patch_file);
+ system_("git am " . ($patch_file_ || $patch_file));
+ $patch_file_ and unlink $patch_file_;
+ } else {
+ system_("patch @opts -i $patch_file");
+
+ my ($patch_name) = $patch_file =~ m!([^/]*)\.(patch|diff)$!;
+
+ system_('git add .');
+ git_commit(commit_line_from_patch_name($patch_name) .
+ (@header ? "\n\n" . join('', cleanup_patch_header(@header)) : ''),
+ # use the date of the patch for the commit:
+ (stat($patch_file))[9] . " +0000");
+ }
+}
+
+sub system_ {
+ my ($cmd) = @_;
+ print "$cmd\n" if $verbose;
+ system($cmd) == 0 or die "$cmd failed\n";
+}
+
+sub git_commit {
+ my ($msg, $date) = @_;
+
+ $ENV{GIT_AUTHOR_DATE} = $date;
+ open(my $F, '| git commit -q --author="unknown <>" --file=-');
+ print $F $msg;
+ close $F or die "git commit failed\n";
+}
+
+sub commit_line_from_patch_name {
+ my ($name) = @_;
+
+ # remove prefix (eg: "libtool-1.5.26-xxx" => "xxx")
+ my $re_name = qr([a-z][\w+]*([_-][a-z][\w+]*)*)i;
+ my $re_rc = qr((rc\d*|RC\d+|beta\d*|pre\d*|p\d+|test));
+ my $re_special_version = qr([a-z]([._-]$re_rc?)?|[._-]?$re_rc?|[a-z]);
+ $name =~ s/^ $re_name [._-] \d+ (\.\d+)+ $re_special_version [._-]//x;
+
+ if (my $pkg_name = $ENV{PKG_NAME}) {
+ $name =~ s/^\Q$pkg_name\E[_-]//;
+ }
+
+ # replace "-" (resp. "_") with spaces if there is no spaces nor "_" (resp. "-")
+ if ($name !~ /[\s_]/ && $name !~ /--/) {
+ $name =~ s/-/ /g;
+ } elsif ($name !~ /[\s-]/ && $name !~ /__/) {
+ $name =~ s/_/ /g;
+ }
+ $name;
+}
+
+sub get_patch_header {
+ my ($file) = @_;
+ open(my $F, '<', $file) or die "can not open $file: $!\n";
+
+ my @header;
+ while (my $s = <$F>) {
+ last if $s =~ /^--- /;
+ push @header, $s;
+ }
+ pop @header while @header && $header[-1] !~ /^\s*$/;
+
+ @header;
+}
+
+sub cleanup_patch_header {
+ my (@header) = @_;
+
+ my @r;
+ foreach (@header) {
+ s/^##\s// or last;
+ push @r, $_;
+ }
+ @r == @header and return @r;
+
+ @header;
+}
+
+# "git format-patch" and "git am" do not agree how to handle commit logs when
+# the first line is not separated from the rest.
+# eg:
+#
+# > Subject: [PATCH 01/34] Delay NSS initialization until actually used
+# > - since NSS is allergic (ie becomes non-functional) after forking, delay
+# > it's initialization until really needed, ie lazy init in rpmDigestInit()
+#
+# workarounding by transforming header to:
+#
+# > Subject: [PATCH 01/34] Delay NSS initialization until actually used
+# >
+# > - since NSS is allergic (ie becomes non-functional) after forking, delay
+# > it's initialization until really needed, ie lazy init in rpmDigestInit()
+sub fix_git_patch {
+ my ($file) = @_;
+ open(my $F, '<', $file) or die "can not open $file: $!\n";
+
+ my ($last_line, @l);
+ while (my $s = <$F>) {
+ push @l, $s;
+
+ if ($s !~ /^\S+:\s/ && $last_line && $last_line =~ /^Subject:/) {
+ # argh, we are in the header, but the value is weird
+ # applying the fix
+ $l[-1] = "\n" . $l[-1];
+ push @l, <$F>;
+ output("$file.tmp", @l);
+ return "$file.tmp";
+ } elsif ($s =~ /^\s*$/ || $s =~ /^--- /) {
+ last;
+ }
+ $last_line = $s;
+ }
+ undef;
+}
+
+sub output { my $f = shift; open(my $F, '>', $f) or die "output in file $f failed: $!\n"; print $F $_ foreach @_; 1 }