Commit eb8b1b87 authored by Leigh Stoller's avatar Leigh Stoller

Make it easier to share the same repository among different profiles:

If there is a directory called "profiles" and there is a file in that
directory named the same as the profile, and ends in a .py (or .rspec),
then use that as the profile source code instead of toplevel profile.py.
parent f2d8902c
#!/usr/bin/perl -w #!/usr/bin/perl -w
# #
# Copyright (c) 2000-2018 University of Utah and the Flux Group. # Copyright (c) 2000-2019 University of Utah and the Flux Group.
# #
# {{{EMULAB-LICENSE # {{{EMULAB-LICENSE
# #
...@@ -108,13 +108,14 @@ sub DoCommitList(); ...@@ -108,13 +108,14 @@ sub DoCommitList();
sub DoCommitInfo(); sub DoCommitInfo();
sub DoGetSource(); sub DoGetSource();
sub DoGetRepoSize(); sub DoGetRepoSize();
sub GetRepoSource($;$); sub GetRepoSource($;$$);
sub GetRepoSize($); sub GetRepoSize($);
sub GetBranchList($); sub GetBranchList($);
sub GetTagList($); sub GetTagList($);
sub GetCommitList($$); sub GetCommitList($$);
sub GetCommitField($$$); sub GetCommitField($$$);
sub GetRepoName($); sub GetRepoName($);
sub GetProfile($);
sub GetDefaultBranch($); sub GetDefaultBranch($);
sub RemoveRepo($); sub RemoveRepo($);
...@@ -266,11 +267,12 @@ sub DoCheckRemote() ...@@ -266,11 +267,12 @@ sub DoCheckRemote()
# #
sub DoClone() sub DoClone()
{ {
my $optlist = "o:rn:u"; my $optlist = "o:rn:uS:";
my $ofile; my $ofile;
my $remove; my $remove;
my $reponame; my $reponame;
my $update; my $update;
my $sourcename;
my %options = (); my %options = ();
if (! getopts($optlist, \%options)) { if (! getopts($optlist, \%options)) {
...@@ -290,6 +292,13 @@ sub DoClone() ...@@ -290,6 +292,13 @@ sub DoClone()
if (defined($options{"r"})) { if (defined($options{"r"})) {
$remove = 1; $remove = 1;
} }
if (defined($options{"S"})) {
$sourcename = $options{"S"};
# Silly taint check.
if ($sourcename =~ /^(.*)$/) {
$sourcename = $1;
}
}
if (defined($options{"u"})) { if (defined($options{"u"})) {
$update = 1; $update = 1;
if (!defined($options{"n"})) { if (!defined($options{"n"})) {
...@@ -344,7 +353,7 @@ sub DoClone() ...@@ -344,7 +353,7 @@ sub DoClone()
# #
# Now get the geni-lib script or rspec, write it to the file or stdout. # Now get the geni-lib script or rspec, write it to the file or stdout.
# #
my $source = GetRepoSource($reponame); my $source = GetRepoSource($reponame, undef, $sourcename);
if (!defined($source)) { if (!defined($source)) {
RemoveRepo($reponame); RemoveRepo($reponame);
UserError("Could not find profile.py or profile.rspec in repository"); UserError("Could not find profile.py or profile.rspec in repository");
...@@ -405,6 +414,7 @@ sub DoUpdate() ...@@ -405,6 +414,7 @@ sub DoUpdate()
my $ofile; my $ofile;
my $reponame; my $reponame;
my $repourl; my $repourl;
my $sourcename;
my %options = (); my %options = ();
if (! getopts($optlist, \%options)) { if (! getopts($optlist, \%options)) {
...@@ -437,6 +447,7 @@ sub DoUpdate() ...@@ -437,6 +447,7 @@ sub DoUpdate()
} }
$reponame = $profile->reponame(); $reponame = $profile->reponame();
$repourl = $profile->repourl(); $repourl = $profile->repourl();
$sourcename = $profile->name();
} }
else { else {
usage(); usage();
...@@ -484,9 +495,9 @@ sub DoUpdate() ...@@ -484,9 +495,9 @@ sub DoUpdate()
# #
# Now get the geni-lib script or rspec write it to the file or stdout. # Now get the geni-lib script or rspec write it to the file or stdout.
# #
my $source = GetRepoSource($reponame); my $source = GetRepoSource($reponame, undef, $sourcename);
if (!defined($source)) { if (!defined($source)) {
UserError("Could not find profile.py or profile.rspec in repository"); UserError("Could not find profile source in repository");
} }
# #
...@@ -534,6 +545,7 @@ sub DoGetSource() ...@@ -534,6 +545,7 @@ sub DoGetSource()
my $reponame; my $reponame;
my $ofile; my $ofile;
my $which; my $which;
my $profile;
my %options = (); my %options = ();
if (! getopts($optlist, \%options)) { if (! getopts($optlist, \%options)) {
...@@ -543,6 +555,7 @@ sub DoGetSource() ...@@ -543,6 +555,7 @@ sub DoGetSource()
$ofile = $options{"o"}; $ofile = $options{"o"};
} }
$which = shift(@ARGV) if (@ARGV); $which = shift(@ARGV) if (@ARGV);
$profile = GetProfile(\%options);
$reponame = GetRepoName(\%options); $reponame = GetRepoName(\%options);
$which = GetDefaultBranch($reponame) if (!defined($which)); $which = GetDefaultBranch($reponame) if (!defined($which));
...@@ -550,7 +563,8 @@ sub DoGetSource() ...@@ -550,7 +563,8 @@ sub DoGetSource()
if ($which =~ /^(.*)$/) { if ($which =~ /^(.*)$/) {
$which = $1; $which = $1;
} }
my $source = GetRepoSource($reponame, $which); my $source = GetRepoSource($reponame, $which,
defined($profile) ? $profile->name() : undef);
if (!defined($source)) { if (!defined($source)) {
UserError("Could not find profile.py or profile.rspec in repository"); UserError("Could not find profile.py or profile.rspec in repository");
} }
...@@ -584,12 +598,18 @@ sub DoGetSource() ...@@ -584,12 +598,18 @@ sub DoGetSource()
# #
# Grab a file from the bare repo. # Grab a file from the bare repo.
# #
sub GetRepoSource($;$) sub GetRepoSource($;$$)
{ {
my ($reponame, $refspec) = @_; my ($reponame, $refspec, $name) = @_;
my $repodir = "$REPODIR/$reponame"; my $repodir = "$REPODIR/$reponame";
my $source; my $source;
# List of places to find the source.
my @locations = ("profiles/profile", "profile");
if (defined($name)) {
unshift(@locations, "profiles/$name", "$name");
}
$refspec = GetDefaultBranch($reponame) $refspec = GetDefaultBranch($reponame)
if (!defined($refspec)); if (!defined($refspec));
...@@ -601,15 +621,19 @@ sub GetRepoSource($;$) ...@@ -601,15 +621,19 @@ sub GetRepoSource($;$)
chdir("$repodir") or chdir("$repodir") or
fatal("Could not chdir to $repodir: $!"); fatal("Could not chdir to $repodir: $!");
if (system("$GIT cat-file -e ". foreach my $maybe (@locations) {
"$refspec:profile.py >/dev/null 2>&1") == 0) { if (system("$GIT cat-file -e ".
$source = "profile.py"; "$refspec:${maybe}.py >/dev/null 2>&1") == 0) {
} $source = "${maybe}.py";
elsif (system("$GIT cat-file -e ". }
" $refspec:profile.rspec >/dev/null 2>&1") == 0) { elsif (system("$GIT cat-file -e ".
$source = "profile.rspec"; " $refspec:${maybe}.rspec >/dev/null 2>&1") == 0) {
$source = "${maybe}.rspec";
}
last
if ($source);
} }
else { if (!$source) {
print STDERR "$repodir, $refspec\n"; print STDERR "$repodir, $refspec\n";
print STDERR `/usr/bin/id`; print STDERR `/usr/bin/id`;
print STDERR `/bin/ls -la`; print STDERR `/bin/ls -la`;
...@@ -1105,6 +1129,27 @@ sub GetRepoName($) ...@@ -1105,6 +1129,27 @@ sub GetRepoName($)
return $reponame; return $reponame;
} }
#
# Dig the profile out of the options list.
#
sub GetProfile($)
{
my ($options) = @_;
my %options = %{ $options };
if (defined($options{"p"})) {
my $profile = APT_Profile->Lookup($options{"p"});
if (!defined($profile)) {
fatal("No such profile");
}
if (!defined($profile->reponame())) {
fatal("No such repository associated with profile");
}
return $profile;
}
return undef;
}
# #
# Estimated Repo size. # Estimated Repo size.
# #
......
...@@ -299,7 +299,8 @@ sub CreateProfile() ...@@ -299,7 +299,8 @@ sub CreateProfile()
my $repohash; my $repohash;
my $output = my $output =
emutil::ExecQuiet("$MANAGEGITREPO clone -n $reponame '$repourl'"); emutil::ExecQuiet("$MANAGEGITREPO clone -n $reponame ".
" -S " . $new_args{"name"} . " '$repourl'");
if ($?) { if ($?) {
UserError($output); UserError($output);
} }
......
...@@ -1449,12 +1449,17 @@ $(function () ...@@ -1449,12 +1449,17 @@ $(function ()
changeRspec(json.value.script); changeRspec(json.value.script);
}); });
} }
var args = {"repourl" : repourl};
// If there is profile name, pass that through so we can look
// for a script or rspec with the same name (instead of profile.py).
if ($.trim($('#profile_name').val()) != "") {
args["profile_name"] = $.trim($('#profile_name').val());
}
WaitWait("We are attempting to clone your repository. " + WaitWait("We are attempting to clone your repository. " +
"Patience please."); "Patience please.");
var xmlthing = sup.CallServerMethod(ajaxurl, var xmlthing = sup.CallServerMethod(ajaxurl,
"manage_profile", "manage_profile",
"GetRepository", "GetRepository", args);
{repourl : repourl});
xmlthing.done(callback); xmlthing.done(callback);
} }
...@@ -1524,7 +1529,7 @@ $(function () ...@@ -1524,7 +1529,7 @@ $(function ()
function SetupRepo() function SetupRepo()
{ {
//console.info("SetupRepo"); console.info("SetupRepo");
gitrepo.InitRepoPicker(version_uuid, reporefspec, gitrepo.InitRepoPicker(version_uuid, reporefspec,
function(which) { function(which) {
......
...@@ -1379,6 +1379,7 @@ function Do_GetRepository() ...@@ -1379,6 +1379,7 @@ function Do_GetRepository()
{ {
global $this_user; global $this_user;
global $ajax_args; global $ajax_args;
$nameopt = "";
$this_idx = $this_user->uid_idx(); $this_idx = $this_user->uid_idx();
$this_uid = $this_user->uid(); $this_uid = $this_user->uid();
...@@ -1394,6 +1395,17 @@ function Do_GetRepository() ...@@ -1394,6 +1395,17 @@ function Do_GetRepository()
} }
$repourl = escapeshellarg($repourl); $repourl = escapeshellarg($repourl);
# Pass though profile name to use instead of profile.py.
if (isset($ajax_args["profile_name"])) {
if (!TBcheck_dbslot($ajax_args["profile_name"],
"apt_profiles", "name",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) {
SPITAJAX_ERROR(2, "Invalid profile name: " . TBFieldErrorString());
return;
}
$nameopt = "-S " . escapeshellarg($ajax_args["profile_name"]);
}
$webtask = WebTask::CreateAnonymous(); $webtask = WebTask::CreateAnonymous();
if (!$webtask) { if (!$webtask) {
SPITAJAX_ERROR(-1, "Internal webtask Error"); SPITAJAX_ERROR(-1, "Internal webtask Error");
...@@ -1409,15 +1421,15 @@ function Do_GetRepository() ...@@ -1409,15 +1421,15 @@ function Do_GetRepository()
SUEXEC_ACTION_IGNORE); SUEXEC_ACTION_IGNORE);
$webtask->Refresh(); $webtask->Refresh();
if ($retval != 0) { if ($retval != 0) {
if ($retval < 0) { if (!$webtask->exited() || $retval < 0) {
$error = $webtask->TaskValue("output"); SUEXECERROR(SUEXEC_ACTION_CONTINUE);
SUEXECERROR(SUEXEC_ACTION_CONTINUE); SPITAJAX_ERROR(-1, "Internal error checking repository");
} }
else { else {
$error = $webtask->TaskValue("output"); $error = $webtask->TaskValue("output");
SPITAJAX_ERROR(1, $error);
} }
$webtask->Delete(); $webtask->Delete();
SPITAJAX_ERROR(1, $error);
return; return;
} }
$webtask->Reset(); $webtask->Reset();
...@@ -1426,20 +1438,20 @@ function Do_GetRepository() ...@@ -1426,20 +1438,20 @@ function Do_GetRepository()
$retval = SUEXEC($this_uid, "tbadmin", $retval = SUEXEC($this_uid, "tbadmin",
"webmanage_gitrepo -t " . $webtask->task_id() . " " . "webmanage_gitrepo -t " . $webtask->task_id() . " " .
" clone -o $outfname -r $repourl", " clone $nameopt -o $outfname -r $repourl",
SUEXEC_ACTION_IGNORE); SUEXEC_ACTION_IGNORE);
$webtask->Refresh(); $webtask->Refresh();
if ($retval != 0) { if ($retval != 0) {
if ($retval < 0) { if (!$webtask->exited() || $retval < 0) {
$error = $webtask->TaskValue("output"); SUEXECERROR(SUEXEC_ACTION_CONTINUE);
SUEXECERROR(SUEXEC_ACTION_CONTINUE); SPITAJAX_ERROR(-1, "Internal error checking repository");
} }
else { else {
$error = $webtask->TaskValue("output"); $error = $webtask->TaskValue("output");
SPITAJAX_ERROR(1, $error);
} }
$webtask->Delete(); $webtask->Delete();
unlink($outfname); unlink($outfname);
SPITAJAX_ERROR(1, $error);
return; return;
} }
$blob = array("script" => file_get_contents($outfname), $blob = array("script" => file_get_contents($outfname),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment