#!/usr/bin/env perl # # This script finds the nearest git commit from an SVN revision. # # In the LLVM repository, all sub-projects are tied together, including their # release branches, so each commit is unique to one repository, and all other # repos have surrounding revision numbers. When we check out from SVN, providing # a number to a repository that doesn't have that revision will bring the last # commit in that repo before the chosen one. # # We need to simulate this here, without having git-svn, so that we can give a # single SVN revision number to a Jenkins job and have any number of # repositories checked out, and all of them guaranteed to be in the right place. # # This script was written for LLVM, but it's generic enough that it doesn't # depend on any LLVM behaviour, and would work on any number of repositories # interlocked in the same way. use strict; use warnings; my $USAGE = "$0 rNNNNN\n"; # Basic checks # This should not be ran by users, so make sure we're at the base of the repo my $BASE = $ARGV[0]; if (not defined $BASE) { die "$USAGE"; } elsif (! -d "$BASE/.git" and ! -f "$BASE/.git") { die "'$BASE' not a git repository.\n$USAGE"; } my $REVISION = $ARGV[1]; if (not defined $REVISION) { die $USAGE; } elsif ($REVISION =~ /^r(\d+)$/) { $REVISION = $1; } else { die "Invalid SVN revision '$REVISION'. $USAGE"; } # Current git/svn info my ($git, $svn); # Walk the log until the exact (or lower) revision is found open LOG, "git -C \"$BASE\" log|" || die "Can't run git log command: $!\n"; foreach my $line () { # Make sure we always update git hashes before SVN id if ($line =~ /^commit ([0-9a-f]+)/) { $git = $1; next; } # When we get to the right SVN revision, just return the last git hash # FIXME: For non-LLVM uses, a different branch may be needed if ($line =~ /^\s+git-svn-id: .*trunk@(\d+) /) { $svn = $1; if ($svn <= $REVISION) { if (not defined $git) { die "Log format error, can't find git commit for SVN '$REVISION'.\n$USAGE"; } print "$svn $git\n"; last; } } } close LOG;