Optimize fetch-git.
This commit is contained in:
@ -315,8 +315,8 @@ sub fetchInputSystemBuild {
|
||||
sub fetchInputGit {
|
||||
my ($db, $project, $jobset, $name, $value) = @_;
|
||||
|
||||
(my $uri, my $branch) = split ' ', $value;
|
||||
$branch = defined $branch ? $branch : "master";
|
||||
(my $uri, my $branch, my $deepClone) = split ' ', $value;
|
||||
$branch = defined $branch ? $branch : "master";
|
||||
|
||||
my $timestamp = time;
|
||||
my $sha256;
|
||||
@ -325,42 +325,64 @@ sub fetchInputGit {
|
||||
mkpath(scmPath);
|
||||
my $clonePath = scmPath . "/" . sha256_hex($uri);
|
||||
|
||||
my $stdout; my $stderr;
|
||||
my $stdout = ""; my $stderr = ""; my $res;
|
||||
if (! -d $clonePath) {
|
||||
(my $res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
# Clone everything and fetch the branch.
|
||||
# TODO: Optimize the first clone by using "git init $clonePath" and "git remote add origin $uri".
|
||||
($res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("git", "clone", "--branch", $branch, $uri, $clonePath));
|
||||
die "Error cloning git repo at `$uri':\n$stderr" unless $res;
|
||||
}
|
||||
|
||||
# git pull + check rev
|
||||
chdir $clonePath or die $!; # !!! urgh, shouldn't do a chdir
|
||||
(my $res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("git", "pull", "--all"));
|
||||
die "Error pulling latest change git repo at `$uri':\n$stderr" unless $res;
|
||||
|
||||
(my $res1, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("git", "ls-remote", $clonePath, $branch));
|
||||
|
||||
die "Cannot get head revision of Git branch '$branch' at `$uri':\n$stderr" unless $res1 ;
|
||||
|
||||
# Take the first commit ID returned by `ls-remote'. The
|
||||
# assumption is that `ls-remote' returned both `refs/heads/BRANCH'
|
||||
# and `refs/remotes/origin/BRANCH', and that both point at the
|
||||
# same commit.
|
||||
my ($first) = split /\n/, $stdout;
|
||||
(my $revision, my $ref) = split ' ', $first;
|
||||
die unless $revision =~ /^[0-9a-fA-F]+$/;
|
||||
|
||||
if (-f ".topdeps") {
|
||||
# This is a TopGit branch. Fetch all the topic branches so
|
||||
# that builders can run "tg patch" and similar.
|
||||
(my $res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("tg", "remote", "--populate", "origin"));
|
||||
|
||||
print STDERR "Warning: `tg remote --populate origin' failed:\n$stderr" unless $res;
|
||||
if (defined $deepClone) {
|
||||
# This fetch every branches from the remote repository and create a
|
||||
# local branch for each heads of the remote repository. This is
|
||||
# necessary to provide a working git-describe.
|
||||
($res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("git", "pull", "--ff-only", "-fu", "--all", "origin"));
|
||||
die "Error pulling latest change from git repo at `$uri':\n$stderr" unless $res;
|
||||
} else {
|
||||
# This command force the update of the local branch to be in the same as
|
||||
# the remote branch for whatever the repository state is. This command mirror
|
||||
# only one branch of the remote repository.
|
||||
($res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("git", "fetch", "-fu", "origin", "+$branch:$branch"));
|
||||
die "Error fetching latest change from git repo at `$uri':\n$stderr" unless $res;
|
||||
}
|
||||
|
||||
# Some simple caching: don't check a uri/branch more than once every hour, but prefer exact match on uri/branch/revision.
|
||||
($res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("git", "rev-parse", "$branch"));
|
||||
die "Error getting revision number of Git branch '$branch' at `$uri':\n$stderr" unless $res;
|
||||
|
||||
my ($revision) = split /\n/, $stdout;
|
||||
die unless $revision =~ /^[0-9a-fA-F]+$/;
|
||||
die "Error getting a well-formated revision number of Git branch '$branch' at `$uri':\n$stdout" unless $res;
|
||||
|
||||
my $ref = "refs/heads/$branch";
|
||||
|
||||
# If deepClone is defined, then we look at the content of the repository
|
||||
# to determine if this is a top-git branch.
|
||||
if (defined $deepClone) {
|
||||
|
||||
# Checkout the branch to look at its content.
|
||||
($res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("git", "checkout", "$branch"));
|
||||
die "Error checking out Git branch '$branch' at `$uri':\n$stderr" unless $res;
|
||||
|
||||
if (-f ".topdeps") {
|
||||
# This is a TopGit branch. Fetch all the topic branches so
|
||||
# that builders can run "tg patch" and similar.
|
||||
($res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("tg", "remote", "--populate", "origin"));
|
||||
|
||||
print STDERR "Warning: `tg remote --populate origin' failed:\n$stderr" unless $res;
|
||||
}
|
||||
}
|
||||
|
||||
# Some simple caching: don't check a uri/branch/revision more than once.
|
||||
# TODO: Fix case where the branch is reset to a previous commit.
|
||||
my $cachedInput ;
|
||||
($cachedInput) = $db->resultset('CachedGitInputs')->search(
|
||||
{uri => $uri, branch => $branch, revision => $revision},
|
||||
@ -371,25 +393,28 @@ sub fetchInputGit {
|
||||
$sha256 = $cachedInput->sha256hash;
|
||||
$revision = $cachedInput->revision;
|
||||
} else {
|
||||
|
||||
# Then download this revision into the store.
|
||||
print STDERR "checking out Git input from $uri\n";
|
||||
print STDERR "checking out Git branch $branch from $uri\n";
|
||||
$ENV{"NIX_HASH_ALGO"} = "sha256";
|
||||
$ENV{"PRINT_PATH"} = "1";
|
||||
|
||||
# Checked out code often wants to be able to run `git
|
||||
# describe', e.g., code that uses Gnulib's `git-version-gen'
|
||||
# script. Thus, we leave `.git' in there. Same for
|
||||
# Subversion (e.g., libgcrypt's build system uses that.)
|
||||
$ENV{"NIX_PREFETCH_GIT_LEAVE_DOT_GIT"} = "1";
|
||||
|
||||
# Ask for a "deep clone" to allow "git describe" and similar
|
||||
# tools to work. See
|
||||
# http://thread.gmane.org/gmane.linux.distributions.nixos/3569
|
||||
# for a discussion.
|
||||
$ENV{"NIX_PREFETCH_GIT_DEEP_CLONE"} = "1";
|
||||
$ENV{"NIX_PREFETCH_GIT_LEAVE_DOT_GIT"} = "0";
|
||||
$ENV{"NIX_PREFETCH_GIT_DEEP_CLONE"} = "";
|
||||
|
||||
(my $res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
if (defined $deepClone) {
|
||||
# Checked out code often wants to be able to run `git
|
||||
# describe', e.g., code that uses Gnulib's `git-version-gen'
|
||||
# script. Thus, we leave `.git' in there. Same for
|
||||
# Subversion (e.g., libgcrypt's build system uses that.)
|
||||
$ENV{"NIX_PREFETCH_GIT_LEAVE_DOT_GIT"} = "1";
|
||||
|
||||
# Ask for a "deep clone" to allow "git describe" and similar
|
||||
# tools to work. See
|
||||
# http://thread.gmane.org/gmane.linux.distributions.nixos/3569
|
||||
# for a discussion.
|
||||
$ENV{"NIX_PREFETCH_GIT_DEEP_CLONE"} = "1";
|
||||
}
|
||||
|
||||
($res, $stdout, $stderr) = captureStdoutStderr(600,
|
||||
("nix-prefetch-git", $clonePath, $revision));
|
||||
die "Cannot check out Git repository branch '$branch' at `$uri':\n$stderr" unless $res;
|
||||
|
||||
@ -509,7 +534,7 @@ sub fetchInputHg {
|
||||
|
||||
# init local hg clone
|
||||
|
||||
my $stdout; my $stderr;
|
||||
my $stdout = ""; my $stderr = "";
|
||||
|
||||
mkpath(scmPath);
|
||||
my $clonePath = scmPath . "/" . sha256_hex($uri);
|
||||
@ -681,7 +706,7 @@ sub captureStdoutStderr {
|
||||
|
||||
if ($@) {
|
||||
die unless $@ eq "timeout\n"; # propagate unexpected errors
|
||||
return (undef, undef, undef);
|
||||
return (undef, "", "timeout\n");
|
||||
} else {
|
||||
return ($res, $stdout, $stderr);
|
||||
}
|
||||
|
Reference in New Issue
Block a user