Browse Source

Merge branch 'master'

maint
Junio C Hamano 19 years ago
parent
commit
77131db585
  1. 4
      .gitignore
  2. 1
      Documentation/.gitignore
  3. 16
      Documentation/Makefile
  4. 28
      Documentation/build-docdep.perl
  5. 56
      Documentation/git-cvsexportcommit.txt
  6. 2
      Documentation/howto/rebase-and-edit.txt
  7. 3
      Documentation/howto/revert-branch-rebase.txt
  8. 2
      Documentation/howto/using-topic-branches.txt
  9. 2
      Makefile
  10. 225
      git-cvsexportcommit.perl
  11. 22
      git-merge-recursive.py
  12. 0
      git-pull.sh
  13. 3
      git-tag.sh
  14. 24
      http-push.c

4
.gitignore vendored

@ -19,6 +19,7 @@ git-commit @@ -19,6 +19,7 @@ git-commit
git-commit-tree
git-convert-objects
git-count-objects
git-cvsexportcommit
git-cvsimport
git-daemon
git-diff
@ -36,6 +37,7 @@ git-get-tar-commit-id @@ -36,6 +37,7 @@ git-get-tar-commit-id
git-grep
git-hash-object
git-http-fetch
git-http-push
git-index-pack
git-init-db
git-local-fetch
@ -107,6 +109,8 @@ git-verify-tag @@ -107,6 +109,8 @@ git-verify-tag
git-whatchanged
git-write-tree
git-core-*/?*
test-date
test-delta
*.tar.gz
*.dsc
*.deb

1
Documentation/.gitignore vendored

@ -3,3 +3,4 @@ @@ -3,3 +3,4 @@
*.1
*.7
howto-index.txt
doc.dep

16
Documentation/Makefile

@ -53,21 +53,19 @@ install: man @@ -53,21 +53,19 @@ install: man
#
# Determine "include::" file references in asciidoc files.
#
TEXTFILES = $(wildcard *.txt)
DEPFILES = $(TEXTFILES:%.txt=%.dep)

%.dep : %.txt
@rm -f $@
@$(foreach dep, $(shell grep include:: $< | sed -e 's/include::/ /' -e 's/\[\]//'), \
echo $(<:%.txt=%.html) $(<:%.txt=%.1) : $(dep) >> $@; )
TEXTFILES = $(wildcard git-*.txt)
doc.dep : $(TEXTFILES) build-docdep.perl
rm -f $@+ $@
perl ./build-docdep.perl >$@+
mv $@+ $@

-include $(DEPFILES)
-include doc.dep

git.7: ../README


clean:
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html *.dep
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep

%.html : %.txt
asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<

28
Documentation/build-docdep.perl

@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
#!/usr/bin/perl

my %include = ();

for my $text (<git-*.txt>) {
open I, '<', $text || die "cannot read: $text";
(my $base = $text) =~ s/\.txt$//;
while (<I>) {
if (/^include::/) {
chomp;
s/^include::\s*//;
s/\[\]//;
$include{$base}{$_} = 1;
}
}
close I;
}

# Do we care about chained includes???

while (my ($base, $included) = each %include) {
my ($suffix) = '1';
if ($base eq 'git') {
$suffix = '7'; # yuck...
}
print "$base.html $base.$suffix : ", join(" ", keys %$included), "\n";
}

56
Documentation/git-cvsexportcommit.txt

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
git-cvsexportcommit(1)
======================

NAME
----
git-cvsexportcommit - Export a commit to a CVS checkout


SYNOPSIS
--------
git-cvsapplycommmit.perl
[ -h ] [ -v ] [ -c ] [ -p ] [PARENTCOMMIT] COMMITID


DESCRIPTION
-----------
Exports a commit from GIT to a CVS checkout, making it easier
to merge patches from a git repository into a CVS repository.

Execute it from the root of the CVS working copy. GIT_DIR must be defined.

It does its best to do the safe thing, it will check that the files are
unchanged and up to date in the CVS checkout, and it will not autocommit
by default.

Supports file additions, removals, and commits that affect binary files.

If the commit is a merge commit, you must tell git-cvsapplycommit what parent
should the changeset be done against.

OPTIONS
-------

-c::
Commit automatically if the patch applied cleanly. It will not
commit if any hunks fail to apply or there were other problems.

-p::
Be pedantic (paranoid) when applying patches. Invokes patch with
--fuzz=0

-v::
Verbose.

Author
------
Written by Martin Langhoff <martin@catalyst.net.nz>

Documentation
--------------
Documentation by Martin Langhoff <martin@catalyst.net.nz>

GIT
---
Part of the gitlink:git[7] suite

2
Documentation/howto/rebase-and-edit.txt

@ -63,7 +63,7 @@ And then, you can just remove the broken branch if you decide you really @@ -63,7 +63,7 @@ And then, you can just remove the broken branch if you decide you really
don't want it:

# remove 'broken' branch
rm .git/refs/heads/broken
git branch -d broken

# Prune old objects if you're really really sure
git prune

3
Documentation/howto/revert-branch-rebase.txt

@ -153,7 +153,8 @@ Everything is in the good order. I do not need the temporary branch @@ -153,7 +153,8 @@ Everything is in the good order. I do not need the temporary branch
nor tag anymore, so remove them:

------------------------------------------------
$ rm -f .git/refs/tags/pu-anchor .git/refs/heads/revert-c99
$ rm -f .git/refs/tags/pu-anchor
$ git branch -d revert-c99
------------------------------------------------

It was an emergency fix, so we might as well merge it into the

2
Documentation/howto/using-topic-branches.txt

@ -166,7 +166,7 @@ output from: @@ -166,7 +166,7 @@ output from:

is empty. At this point the branch can be deleted:

$ rm .git/refs/heads/branchname
$ git branch -d branchname

Some changes are so trivial that it is not necessary to create a separate
branch and then merge into each of the test and release branches. For

2
Makefile

@ -93,7 +93,7 @@ SCRIPT_SH = \ @@ -93,7 +93,7 @@ SCRIPT_SH = \
SCRIPT_PERL = \
git-archimport.perl git-cvsimport.perl git-relink.perl \
git-rename.perl git-shortlog.perl git-fmt-merge-msg.perl \
git-svnimport.perl git-mv.perl
git-svnimport.perl git-mv.perl git-cvsexportcommit.perl

SCRIPT_PYTHON = \
git-merge-recursive.py

225
git-cvsexportcommit.perl

@ -0,0 +1,225 @@ @@ -0,0 +1,225 @@
#!/usr/bin/perl -w

use strict;
use Getopt::Std;
use File::Temp qw(tempdir);
use Data::Dumper;

unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){
die "GIT_DIR is not defined or is unreadable";
}

our ($opt_h, $opt_p, $opt_v, $opt_c );

getopt('hpvc');

$opt_h && usage();

die "Need at least one commit identifier!" unless @ARGV;

# setup a tempdir
our ($tmpdir, $tmpdirname) = tempdir('git-cvsapplycommit-XXXXXX',
TMPDIR => 1,
CLEANUP => 1);

print Dumper(@ARGV);
# resolve target commit
my $commit;
$commit = pop @ARGV;
$commit = `git-rev-parse --verify "$commit"^0`;
chomp $commit;
if ($?) {
die "The commit reference $commit did not resolve!";
}

# resolve what parent we want
my $parent;
if (@ARGV) {
$parent = pop @ARGV;
$parent = `git-rev-parse --verify "$parent"^0"`;
chomp $parent;
if ($?) {
die "The parent reference did not resolve!";
}
}

# find parents from the commit itself
my @commit = `git-cat-file commit $commit`;
my @parents;
foreach my $p (@commit) {
if ($p =~ m/^$/) { # end of commit headers, we're done
last;
}
if ($p =~ m/^parent (\w{40})$/) { # found a parent
push @parents, $1;
}
}

if ($parent) {
# double check that it's a valid parent
foreach my $p (@parents) {
my $found;
if ($p eq $parent) {
$found = 1;
last;
}; # found it
die "Did not find $parent in the parents for this commit!";
s }
} else { # we don't have a parent from the cmdline...
if (@parents == 1) { # it's safe to get it from the commit
$parent = $parents[0];
} else { # or perhaps not!
die "This commit has more than one parent -- please name the parent you want to use explicitly";
}
}

$opt_v && print "Applying to CVS commit $commit from parent $parent\n";

# grab the commit message
`git-cat-file commit $commit | sed -e '1,/^\$/d' > .msg`;
$? && die "Error extraction the commit message";

my (@afiles, @dfiles, @mfiles);
my @files = `git-diff-tree -r $parent $commit`;
print @files;
$? && die "Error in git-diff-tree";
foreach my $f (@files) {
chomp $f;
my @fields = split(m/\s+/, $f);
if ($fields[4] eq 'A') {
push @afiles, $fields[5];
}
if ($fields[4] eq 'M') {
push @mfiles, $fields[5];
}
if ($fields[4] eq 'R') {
push @dfiles, $fields[5];
}
}
$opt_v && print "The commit affects:\n ";
$opt_v && print join ("\n ", @afiles,@mfiles,@dfiles) . "\n\n";
undef @files; # don't need it anymore

# check that the files are clean and up to date according to cvs
my $dirty;
foreach my $f (@afiles, @mfiles, @dfiles) {
# TODO:we need to handle removed in cvs and/or new (from git)
my $status = `cvs -q status "$f" | grep '^File: '`;

unless ($status =~ m/Status: Up-to-date$/) {
$dirty = 1;
warn "File $f not up to date in your CVS checkout!\n";
}
}
if ($dirty) {
die "Exiting: your CVS tree is not clean for this merge.";
}

###
### NOTE: if you are planning to die() past this point
### you MUST call cleanupcvs(@files) before die()
###


print "'Patching' binary files\n";

my @bfiles = `git-diff-tree -p $parent $commit | grep '^Binary'`;
@bfiles = map { chomp } @bfiles;
foreach my $f (@bfiles) {
# check that the file in cvs matches the "old" file
# extract the file to $tmpdir and comparre with cmp
my $tree = `git-rev-parse $parent^{tree} `;
chomp $tree;
my $blob = `git-ls-tree $tree "$f" | cut -f 1 | cut -d ' ' -f 3`;
chomp $blob;
`git-cat-file blob $blob > $tmpdir/blob`;
`cmp -q $f $tmpdir/blob`;
if ($?) {
warn "Binary file $f in CVS does not match parent.\n";
$dirty = 1;
next;
}

# replace with the new file
`git-cat-file blob $blob > $f`;

# TODO: something smart with file modes

}
if ($dirty) {
cleanupcvs(@files);
die "Exiting: Binary files in CVS do not match parent";
}

## apply non-binary changes
my $fuzz = $opt_p ? 0 : 2;

print "Patching non-binary files\n";
print `(git-diff-tree -p $parent -p $commit | patch -p1 -F $fuzz ) 2>&1`;

my $dirtypatch = 0;
if (($? >> 8) == 2) {
cleanupcvs(@files);
die "Exiting: Patch reported serious trouble -- you will have to apply this patch manually";
} elsif (($? >> 8) == 1) { # some hunks failed to apply
$dirtypatch = 1;
}

foreach my $f (@afiles) {
`cvs add $f`;
if ($?) {
$dirty = 1;
warn "Failed to cvs add $f -- you may need to do it manually";
}
}

foreach my $f (@dfiles) {
`cvs rm -f $f`;
if ($?) {
$dirty = 1;
warn "Failed to cvs rm -f $f -- you may need to do it manually";
}
}

print "Commit to CVS\n";
my $commitfiles = join(' ', @afiles, @mfiles, @dfiles);
my $cmd = "cvs commit -F .msg $commitfiles";

if ($dirtypatch) {
print "NOTE: One or more hunks failed to apply cleanly.\n";
print "Resolve the conflicts and then commit using:n";
print "\n $cmd\n\n";
exit;
}


if ($opt_c) {
print "Autocommit\n $cmd\n";
print `cvs commit -F .msg $commitfiles 2>&1`;
if ($?) {
cleanupcvs(@files);
die "Exiting: The commit did not succeed";
}
print "Committed successfully to CVS\n";
} else {
print "Ready for you to commit, just run:\n\n $cmd\n";
}
sub usage {
print STDERR <<END;
Usage: GIT_DIR=/path/to/.gi ${\basename $0} # fetch/update GIT from CVS
[-h] [-p] [ parent ] commit
END
exit(1);
}

# ensure cvs is clean before we die
sub cleanupcvs {
my @files = @_;
foreach my $f (@files) {
`cvs -q update -C "$f"`;
if ($?) {
warn "Warning! Failed to cleanup state of $f\n";
}
}
}

22
git-merge-recursive.py

@ -162,10 +162,13 @@ def mergeTrees(head, merge, common, branch1Name, branch2Name): @@ -162,10 +162,13 @@ def mergeTrees(head, merge, common, branch1Name, branch2Name):
# Low level file merging, update and removal
# ------------------------------------------

MERGE_NONE = 0
MERGE_TRIVIAL = 1
MERGE_3WAY = 2
def mergeFile(oPath, oSha, oMode, aPath, aSha, aMode, bPath, bSha, bMode,
branch1Name, branch2Name):

merge = False
merge = MERGE_NONE
clean = True

if stat.S_IFMT(aMode) != stat.S_IFMT(bMode):
@ -178,7 +181,7 @@ def mergeFile(oPath, oSha, oMode, aPath, aSha, aMode, bPath, bSha, bMode, @@ -178,7 +181,7 @@ def mergeFile(oPath, oSha, oMode, aPath, aSha, aMode, bPath, bSha, bMode,
sha = bSha
else:
if aSha != oSha and bSha != oSha:
merge = True
merge = MERGE_TRIVIAL

if aMode == oMode:
mode = bMode
@ -207,7 +210,8 @@ def mergeFile(oPath, oSha, oMode, aPath, aSha, aMode, bPath, bSha, bMode, @@ -207,7 +210,8 @@ def mergeFile(oPath, oSha, oMode, aPath, aSha, aMode, bPath, bSha, bMode,
os.unlink(orig)
os.unlink(src1)
os.unlink(src2)

merge = MERGE_3WAY
clean = (code == 0)
else:
assert(stat.S_ISLNK(aMode) and stat.S_ISLNK(bMode))
@ -577,14 +581,16 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): @@ -577,14 +581,16 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
updateFile(False, ren1.dstSha, ren1.dstMode, dstName1)
updateFile(False, ren2.dstSha, ren2.dstMode, dstName2)
else:
print 'Renaming', fmtRename(path, ren1.dstName)
[resSha, resMode, clean, merge] = \
mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode,
ren1.dstName, ren1.dstSha, ren1.dstMode,
ren2.dstName, ren2.dstSha, ren2.dstMode,
branchName1, branchName2)

if merge:
if merge or not clean:
print 'Renaming', fmtRename(path, ren1.dstName)

if merge == MERGE_3WAY:
print 'Auto-merging', ren1.dstName

if not clean:
@ -653,14 +659,16 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): @@ -653,14 +659,16 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB):
tryMerge = True

if tryMerge:
print 'Renaming', fmtRename(ren1.srcName, ren1.dstName)
[resSha, resMode, clean, merge] = \
mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode,
ren1.dstName, ren1.dstSha, ren1.dstMode,
ren1.srcName, srcShaOtherBranch, srcModeOtherBranch,
branchName1, branchName2)

if merge:
if merge or not clean:
print 'Renaming', fmtRename(ren1.srcName, ren1.dstName)

if merge == MERGE_3WAY:
print 'Auto-merging', ren1.dstName

if not clean:

0
git-pull.sh

3
git-tag.sh

@ -92,5 +92,6 @@ if [ "$annotate" ]; then @@ -92,5 +92,6 @@ if [ "$annotate" ]; then
object=$(git-mktag < "$GIT_DIR"/TAG_TMP)
fi

mkdir -p "$GIT_DIR/refs/tags"
leading=`expr "refs/tags/$name" : '\(.*\)/'` &&
mkdir -p "$GIT_DIR/$leading" &&
echo $object > "$GIT_DIR/refs/tags/$name"

24
http-push.c

@ -28,6 +28,15 @@ static const char http_push_usage[] = @@ -28,6 +28,15 @@ static const char http_push_usage[] =
#define NO_CURL_EASY_DUPHANDLE
#endif

#ifndef XML_STATUS_OK
enum XML_Status {
XML_STATUS_OK = 1,
XML_STATUS_ERROR = 0
};
#define XML_STATUS_OK 1
#define XML_STATUS_ERROR 0
#endif

#define RANGE_HEADER_SIZE 30

/* DAV method names and request body templates */
@ -47,6 +56,7 @@ static int active_requests = 0; @@ -47,6 +56,7 @@ static int active_requests = 0;
static int data_received;
static int pushing = 0;
static int aborted = 0;
static char remote_dir_exists[256];

#ifdef USE_CURL_MULTI
static int max_requests = -1;
@ -650,6 +660,7 @@ static void finish_request(struct transfer_request *request) @@ -650,6 +660,7 @@ static void finish_request(struct transfer_request *request)
if (request->http_code == 404) {
request->state = NEED_PUSH;
} else if (request->curl_result == CURLE_OK) {
remote_dir_exists[request->sha1[0]] = 1;
request->state = COMPLETE;
} else {
fprintf(stderr, "HEAD %s failed, aborting (%d/%ld)\n",
@ -661,6 +672,7 @@ static void finish_request(struct transfer_request *request) @@ -661,6 +672,7 @@ static void finish_request(struct transfer_request *request)
} else if (request->state == RUN_MKCOL) {
if (request->curl_result == CURLE_OK ||
request->http_code == 405) {
remote_dir_exists[request->sha1[0]] = 1;
start_put(request);
} else {
fprintf(stderr, "MKCOL %s failed, aborting (%d/%ld)\n",
@ -728,11 +740,12 @@ void process_curl_messages(void) @@ -728,11 +740,12 @@ void process_curl_messages(void)
slot->curl != curl_message->easy_handle)
slot = slot->next;
if (slot != NULL) {
int curl_result = curl_message->data.result;
curl_multi_remove_handle(curlm, slot->curl);
active_requests--;
slot->done = 1;
slot->in_use = 0;
slot->curl_result = curl_message->data.result;
slot->curl_result = curl_result;
curl_easy_getinfo(slot->curl,
CURLINFO_HTTP_CODE,
&slot->http_code);
@ -767,7 +780,10 @@ void process_request_queue(void) @@ -767,7 +780,10 @@ void process_request_queue(void)
start_check(request);
curl_multi_perform(curlm, &num_transfers);
} else if (pushing && request->state == NEED_PUSH) {
start_mkcol(request);
if (remote_dir_exists[request->sha1[0]])
start_put(request);
else
start_mkcol(request);
curl_multi_perform(curlm, &num_transfers);
}
request = request->next;
@ -1230,7 +1246,7 @@ struct active_lock *lock_remote(char *file, long timeout) @@ -1230,7 +1246,7 @@ struct active_lock *lock_remote(char *file, long timeout)
in_buffer.posn = 0;
in_buffer.buffer = in_data;

new_lock = xmalloc(sizeof(*new_lock));
new_lock = xcalloc(1, sizeof(*new_lock));
new_lock->owner = NULL;
new_lock->token = NULL;
new_lock->timeout = -1;
@ -1599,6 +1615,8 @@ int main(int argc, char **argv) @@ -1599,6 +1615,8 @@ int main(int argc, char **argv)
break;
}

memset(remote_dir_exists, 0, 256);

curl_global_init(CURL_GLOBAL_ALL);

#ifdef USE_CURL_MULTI

Loading…
Cancel
Save