16 # Import an external git repository into the OpenAFS tree, taking the path
17 # to a local clone of that repository, a file containing a list of mappings
18 # between that repository and the location in the OpenAFS one, and optionally
24 my $result = GetOptions("help|?" => \$help,
26 "externaldir=s" => \$externalDir);
28 pod2usage(1) if $help;
29 pod2usage(-existatus => 0, -verbose =>2) if $man;
32 my $clonePath = shift;
33 my $commitish = shift;
35 pod2usage(2) if !defined($module) || !defined($clonePath);
41 # Use the PROGRAM_NAME to work out where we should be importing to.
43 $externalDir = dirname(Cwd::abs_path($PROGRAM_NAME));
46 # Read in our mapping file
48 my $fh = IO::File->new("$externalDir/$module-files")
49 or die "Couldn't open mapping file : $!\n";
52 if (/^(\S+)\s+(\S+)$/) {
55 die "Unrecognised line in mapping file : $_\n";
60 # Create the external directory, if it doesn't exist.
61 mkdir "$externalDir/$module" if (! -d "$externalDir/$module");
63 # Make ourselves a temporary directory
64 my $tempdir = File::Temp::tempdir(CLEANUP => 1);
66 # Write a list of all of the files that we're going to want out of the other
67 # repository in a format we can use with tar.
68 $fh = IO::File->new($tempdir."/filelist", "w")
69 or die "Can't open temporary file list for writing\n";
70 foreach (sort keys(%mapping)) {
71 $fh->print("source/".$_."\n");
75 # Change directory to the root of the source repository
77 or die "Unable to change directory to $clonePath : $!\n";
79 # Figure out some better names for the commit object we're using
80 my $commitSha1 = `git rev-parse $commitish`;
81 my $commitDesc = `git describe $commitish`;
85 # Populate our temporary directory with the originals of everything that was
86 # listed in the mapping file
87 system("git archive --format=tar --prefix=source/ $commitish".
88 " | tar -x -C $tempdir -T $tempdir/filelist") == 0
89 or die "git archive and tar failed : $!\n";
91 # change our CWD to the module directory - git ls-files seems to require this
92 chdir "$externalDir/$module"
93 or die "Unable to change directory to $externalDir/$module : $!\n";
95 # Now we're about to start fiddling with local state. Make a note of where we
98 # Use git stash to preserve whatever state there may be in the current
99 # working tree. Sadly git stash returns a 0 exit status if there are no
100 # local changes, so we need to check for local changes first.
103 if (system("git diff-index --quiet --cached HEAD --ignore-submodules") != 0 ||
104 system("git diff-files --quiet --ignore-submodules") != 0) {
105 if (system("git stash") != 0) {
106 die "git stash failed with : $!\n";
112 # Use git-ls-files to get the list of currently committed files for the module
113 my $lspipe = IO::Pipe->new();
114 $lspipe->reader(qw(git ls-files));
122 foreach my $source (sort keys(%mapping)) {
123 if (-f "$tempdir/source/$source") {
124 File::Path::make_path(File::Basename::dirname($mapping{$source}));
125 system("cp $tempdir/source/$source ".
126 " $externalDir/$module/".$mapping{$source}) == 0
127 or die "Copy failed with $!\n";
128 system("git add $externalDir/$module/".$mapping{$source}) == 0
129 or die "git add failed with $!\n";
130 delete $filesInTree{$mapping{$source}}
132 die "Couldn't find file $source in original tree\n";
136 # Use git rm to delete everything that's committed that we don't have a
138 foreach my $missing (keys(%filesInTree)) {
139 system("git rm $missing") == 0
140 or die "Couldn't git rm $missing : $!\n";
143 if (system("git status") == 0) {
144 my $fh=IO::File->new("$tempdir/commit-msg", "w")
145 or die "Unable to write commit message\n";
146 $fh->print("Import of code from $module\n");
148 $fh->print("This commit updates the code imported from the external\n");
149 $fh->print("$module git repository to their revision\n$commitSha1\n");
150 $fh->print("which is described as $commitDesc\n");
152 system("git commit -F $tempdir/commit-msg") == 0
153 or die "Commit failed : $!\n";
160 print STDERR "Import failed with $@\n";
161 print STDERR "Attempting to reset back to where we were ...\n";
162 system("git reset --hard HEAD") == 0
163 or die "Unable to reset, sorry. You'll need to pick up the pieces\n";
168 system("git stash pop") == 0
169 or die "git stash pop failed with : $!\n";
178 import-external-git - Import bits of an external git repo to OpenAFS
182 import-external-git [options] <module> <repository> [<commitish>]
185 --help brief help message
186 --man full documentation
187 --externalDir exact path to import into
191 import-external-git imports selected files from an external git repository
192 into the OpenAFS src/external tree. For a given <module> it assumes that
193 src/external/<module>-files already exists, and contains a space separated
194 list of source and destination file names. <repository> should point to a
195 local clone of the external project's git repository, and <commitish> points
196 to an object within that tree. If <commitish> isn't specified, the current
197 branch HEAD of that repository is used.