return 0;
}
- my @gitvars = `git-repo-config -l`;
+ my @gitvars = `git-config -l`;
if ($?) {
- print "E problems executing git-repo-config on the server -- this is not a git repository or the PATH is not set correctly.\n";
+ print "E problems executing git-config on the server -- this is not a git repository or the PATH is not set correctly.\n";
print "E \n";
- print "error 1 - problem executing git-repo-config\n";
+ print "error 1 - problem executing git-config\n";
return 0;
}
foreach my $line ( @gitvars )
print "Checked-in $dirpart\n";
print "$filename\n";
- print "/$filepart/0///\n";
+ my $kopts = kopts_from_path($filepart);
+ print "/$filepart/0//$kopts/\n";
$addcount++;
}
print "Checked-in $dirpart\n";
print "$filename\n";
- print "/$filepart/-1.$wrev///\n";
+ my $kopts = kopts_from_path($filepart);
+ print "/$filepart/-1.$wrev//$kopts/\n";
$rmcount++;
}
print $state->{CVSROOT} . "/$module/" . ( defined ( $git->{dir} ) and $git->{dir} ne "./" ? $git->{dir} . "/" : "" ) . "$git->{name}\n";
# this is an "entries" line
- print "/$git->{name}/1.$git->{revision}///\n";
+ my $kopts = kopts_from_path($git->{name});
+ print "/$git->{name}/1.$git->{revision}//$kopts/\n";
# permissions
print "u=$git->{mode},g=$git->{mode},o=$git->{mode}\n";
print "MT newline\n";
next;
}
- elsif ( !defined($wrev) || $wrev == 0 )
+ elsif ( (!defined($wrev) || $wrev == 0) && (!defined($meta->{revision}) || $meta->{revision} == 0) )
{
- $log->info("Tell the client the file will be added");
+ $log->info("Tell the client the file is scheduled for addition");
print "MT text A \n";
print "MT fname $filename\n";
print "MT newline\n";
}
else {
- $log->info("Updating '$filename' $wrev");
+ $log->info("Updating '$filename' to ".$meta->{revision});
print "MT +updated\n";
print "MT text U \n";
print "MT fname $filename\n";
print $state->{CVSROOT} . "/$state->{module}/$filename\n";
# this is an "entries" line
- $log->debug("/$filepart/1.$meta->{revision}///");
- print "/$filepart/1.$meta->{revision}///\n";
+ my $kopts = kopts_from_path($filepart);
+ $log->debug("/$filepart/1.$meta->{revision}//$kopts/");
+ print "/$filepart/1.$meta->{revision}//$kopts/\n";
# permissions
$log->debug("SEND : u=$meta->{mode},g=$meta->{mode},o=$meta->{mode}");
# we need to merge with the local changes ( M=successful merge, C=conflict merge )
$log->info("Merging $file_local, $file_old, $file_new");
+ print "M Merging differences between 1.$oldmeta->{revision} and 1.$meta->{revision} into $filename\n";
$log->debug("Temporary directory for merge is $dir");
{
$log->info("Merged successfully");
print "M M $filename\n";
- $log->debug("Update-existing $dirpart");
+ $log->debug("Merged $dirpart");
# Don't want to actually _DO_ the update if -n specified
unless ( $state->{globaloptions}{-n} )
{
- print "Update-existing $dirpart\n";
+ print "Merged $dirpart\n";
$log->debug($state->{CVSROOT} . "/$state->{module}/$filename");
print $state->{CVSROOT} . "/$state->{module}/$filename\n";
- $log->debug("/$filepart/1.$meta->{revision}///");
- print "/$filepart/1.$meta->{revision}///\n";
+ my $kopts = kopts_from_path($filepart);
+ $log->debug("/$filepart/1.$meta->{revision}//$kopts/");
+ print "/$filepart/1.$meta->{revision}//$kopts/\n";
}
}
elsif ( $return == 1 )
{
$log->info("Merged with conflicts");
+ print "E cvs update: conflicts found in $filename\n";
print "M C $filename\n";
# Don't want to actually _DO_ the update if -n specified
unless ( $state->{globaloptions}{-n} )
{
- print "Update-existing $dirpart\n";
+ print "Merged $dirpart\n";
print $state->{CVSROOT} . "/$state->{module}/$filename\n";
- print "/$filepart/1.$meta->{revision}/+//\n";
+ my $kopts = kopts_from_path($filepart);
+ print "/$filepart/1.$meta->{revision}/+/$kopts/\n";
}
}
else
exit;
}
- my $lockfile = "$state->{CVSROOT}/refs/heads/$state->{module}.lock";
- unless ( sysopen(LOCKFILE,$lockfile,O_EXCL|O_CREAT|O_WRONLY) )
- {
- $log->warn("lockfile '$lockfile' already exists, please try again");
- print "error 1 Lock file '$lockfile' already exists, please try again\n";
- exit;
- }
-
# Grab a handle to the SQLite db and do any necessary updates
my $updater = GITCVS::updater->new($state->{CVSROOT}, $state->{module}, $log);
$updater->update();
my $tmpdir = tempdir ( DIR => $TEMP_DIR );
my ( undef, $file_index ) = tempfile ( DIR => $TEMP_DIR, OPEN => 0 );
- $log->info("Lock successful, basing commit on '$tmpdir', index file is '$file_index'");
+ $log->info("Lockless commit start, basing commit on '$tmpdir', index file is '$file_index'");
$ENV{GIT_DIR} = $state->{CVSROOT} . "/";
$ENV{GIT_INDEX_FILE} = $file_index;
+ # Remember where the head was at the beginning.
+ my $parenthash = `git show-ref -s refs/heads/$state->{module}`;
+ chomp $parenthash;
+ if ($parenthash !~ /^[0-9a-f]{40}$/) {
+ print "error 1 pserver cannot find the current HEAD of module";
+ exit;
+ }
+
chdir $tmpdir;
# populate the temporary index based
- system("git-read-tree", $state->{module});
+ system("git-read-tree", $parenthash);
unless ($? == 0)
{
die "Error running git-read-tree $state->{module} $file_index $!";
}
$log->info("Created index '$file_index' with for head $state->{module} - exit status $?");
-
my @committedfiles = ();
+ my %oldmeta;
# foreach file specified on the command line ...
foreach my $filename ( @{$state->{args}} )
next unless ( exists $state->{entries}{$filename}{modified_filename} or not $state->{entries}{$filename}{unchanged} );
my $meta = $updater->getmeta($filename);
+ $oldmeta{$filename} = $meta;
my $wrev = revparse($filename);
{
# fail everything if an up to date check fails
print "error 1 Up to date check failed for $filename\n";
- close LOCKFILE;
- unlink($lockfile);
chdir "/";
exit;
}
{
print "E No files to commit\n";
print "ok\n";
- close LOCKFILE;
- unlink($lockfile);
chdir "/";
return;
}
my $treehash = `git-write-tree`;
- my $parenthash = `cat $ENV{GIT_DIR}refs/heads/$state->{module}`;
chomp $treehash;
- chomp $parenthash;
$log->debug("Treehash : $treehash, Parenthash : $parenthash");
close $msg_fh;
my $commithash = `git-commit-tree $treehash -p $parenthash < $msg_filename`;
+ chomp($commithash);
$log->info("Commit hash : $commithash");
unless ( $commithash =~ /[a-zA-Z0-9]{40}/ )
{
$log->warn("Commit failed (Invalid commit hash)");
print "error 1 Commit failed (unknown reason)\n";
- close LOCKFILE;
- unlink($lockfile);
chdir "/";
exit;
}
- print LOCKFILE $commithash;
+ # Check that this is allowed, just as we would with a receive-pack
+ my @cmd = ( $ENV{GIT_DIR}.'hooks/update', "refs/heads/$state->{module}",
+ $parenthash, $commithash );
+ if( -x $cmd[0] ) {
+ unless( system( @cmd ) == 0 )
+ {
+ $log->warn("Commit failed (update hook declined to update ref)");
+ print "error 1 Commit failed (update hook declined)\n";
+ chdir "/";
+ exit;
+ }
+ }
+
+ if (system(qw(git update-ref -m), "cvsserver ci",
+ "refs/heads/$state->{module}", $commithash, $parenthash)) {
+ $log->warn("update-ref for $state->{module} failed.");
+ print "error 1 Cannot commit -- update first\n";
+ exit;
+ }
$updater->update();
$log->debug("Checked-in $dirpart : $filename");
+ print "M $state->{CVSROOT}/$state->{module}/$filename,v <-- $dirpart$filepart\n";
if ( defined $meta->{filehash} && $meta->{filehash} eq "deleted" )
{
+ print "M new revision: delete; previous revision: 1.$oldmeta{$filename}{revision}\n";
print "Remove-entry $dirpart\n";
print "$filename\n";
} else {
+ if ($meta->{revision} == 1) {
+ print "M initial revision: 1.1\n";
+ } else {
+ print "M new revision: 1.$meta->{revision}; previous revision: 1.$oldmeta{$filename}{revision}\n";
+ }
print "Checked-in $dirpart\n";
print "$filename\n";
- print "/$filepart/1.$meta->{revision}///\n";
+ my $kopts = kopts_from_path($filepart);
+ print "/$filepart/1.$meta->{revision}//$kopts/\n";
}
}
- close LOCKFILE;
- my $reffile = "$ENV{GIT_DIR}refs/heads/$state->{module}";
- unlink($reffile);
- rename($lockfile, $reffile);
chdir "/";
-
print "ok\n";
}
}
if ( defined($meta->{revision}) )
{
- print "M Repository revision:\t1." . $meta->{revision} . "\t$state->{repository}/$filename,v\n";
+ print "M Repository revision:\t1." . $meta->{revision} . "\t$state->{CVSROOT}/$state->{module}/$filename,v\n";
print "M Sticky Tag:\t\t(none)\n";
print "M Sticky Date:\t\t(none)\n";
print "M Sticky Options:\t\t(none)\n";
return $filename;
}
+# Given a path, this function returns a string containing the kopts
+# that should go into that path's Entries line. For example, a binary
+# file should get -kb.
+sub kopts_from_path
+{
+ my ($path) = @_;
+
+ # Once it exists, the git attributes system should be used to look up
+ # what attributes apply to this path.
+
+ # Until then, take the setting from the config file
+ unless ( defined ( $cfg->{gitcvs}{allbinary} ) and $cfg->{gitcvs}{allbinary} =~ /^\s*(1|true|yes)\s*$/i )
+ {
+ # Return "" to give no special treatment to any path
+ return "";
+ } else {
+ # Alternatively, to have all files treated as if they are binary (which
+ # is more like git itself), always return the "-kb" option
+ return "-kb";
+ }
+}
+
package GITCVS::log;
####