Merge branch 'js/diff'

This commit is contained in:
Junio C Hamano
2006-06-17 17:08:36 -07:00
60 changed files with 3249 additions and 390 deletions

View File

@ -20,7 +20,10 @@ OPTIONS
Use the same output mode as git-annotate (Default: off). Use the same output mode as git-annotate (Default: off).
-l, --long:: -l, --long::
Show long rev (Defaults off). Show long rev (Default: off).
-t, --time::
Show raw timestamp (Default: off).
-S, --rev-file <revs-file>:: -S, --rev-file <revs-file>::
Use revs from revs-file instead of calling git-rev-list. Use revs from revs-file instead of calling git-rev-list.

View File

@ -8,7 +8,7 @@ git-p4import - Import a Perforce repository into git
SYNOPSIS SYNOPSIS
-------- --------
`git-p4import` [-q|-v] [--authors <file>] [-t <timezone>] <//p4repo/path> <branch> `git-p4import` [-q|-v] [--notags] [--authors <file>] [-t <timezone>] <//p4repo/path> <branch>
`git-p4import` --stitch <//p4repo/path> `git-p4import` --stitch <//p4repo/path>
@ -43,6 +43,9 @@ OPTIONS
Specify an authors file containing a mapping of Perforce user Specify an authors file containing a mapping of Perforce user
ids to full names and email addresses (see Notes below). ids to full names and email addresses (see Notes below).
\--notags::
Do not create a tag for each imported commit.
\--stitch:: \--stitch::
Import the contents of the given perforce branch into the Import the contents of the given perforce branch into the
currently checked out git branch. currently checked out git branch.

24
blame.c
View File

@ -20,9 +20,11 @@
#define DEBUG 0 #define DEBUG 0
static const char blame_usage[] = "[-c] [-l] [--] file [commit]\n" static const char blame_usage[] = "[-c] [-l] [-t] [-S <revs-file>] [--] file [commit]\n"
" -c, --compability Use the same output mode as git-annotate (Default: off)\n" " -c, --compability Use the same output mode as git-annotate (Default: off)\n"
" -l, --long Show long commit SHA1 (Default: off)\n" " -l, --long Show long commit SHA1 (Default: off)\n"
" -t, --time Show raw timestamp (Default: off)\n"
" -S, --revs-file Use revisions from revs-file instead of calling git-rev-list\n"
" -h, --help This message"; " -h, --help This message";
static struct commit **blame_lines; static struct commit **blame_lines;
@ -680,13 +682,19 @@ static void get_commit_info(struct commit* commit, struct commit_info* ret)
*tmp = 0; *tmp = 0;
} }
static const char* format_time(unsigned long time, const char* tz_str) static const char* format_time(unsigned long time, const char* tz_str,
int show_raw_time)
{ {
static char time_buf[128]; static char time_buf[128];
time_t t = time; time_t t = time;
int minutes, tz; int minutes, tz;
struct tm *tm; struct tm *tm;
if (show_raw_time) {
sprintf(time_buf, "%lu %s", time, tz_str);
return time_buf;
}
tz = atoi(tz_str); tz = atoi(tz_str);
minutes = tz < 0 ? -tz : tz; minutes = tz < 0 ? -tz : tz;
minutes = (minutes / 100)*60 + (minutes % 100); minutes = (minutes / 100)*60 + (minutes % 100);
@ -740,6 +748,7 @@ int main(int argc, const char **argv)
char filename_buf[256]; char filename_buf[256];
int sha1_len = 8; int sha1_len = 8;
int compability = 0; int compability = 0;
int show_raw_time = 0;
int options = 1; int options = 1;
struct commit* start_commit; struct commit* start_commit;
@ -768,6 +777,10 @@ int main(int argc, const char **argv)
!strcmp(argv[i], "--compability")) { !strcmp(argv[i], "--compability")) {
compability = 1; compability = 1;
continue; continue;
} else if(!strcmp(argv[i], "-t") ||
!strcmp(argv[i], "--time")) {
show_raw_time = 1;
continue;
} else if(!strcmp(argv[i], "-S")) { } else if(!strcmp(argv[i], "-S")) {
if (i + 1 < argc && if (i + 1 < argc &&
!read_ancestry(argv[i + 1], &sha1_p)) { !read_ancestry(argv[i + 1], &sha1_p)) {
@ -873,14 +886,17 @@ int main(int argc, const char **argv)
fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout); fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
if(compability) { if(compability) {
printf("\t(%10s\t%10s\t%d)", ci.author, printf("\t(%10s\t%10s\t%d)", ci.author,
format_time(ci.author_time, ci.author_tz), i+1); format_time(ci.author_time, ci.author_tz,
show_raw_time),
i+1);
} else { } else {
if (found_rename) if (found_rename)
printf(" %-*.*s", longest_file, longest_file, printf(" %-*.*s", longest_file, longest_file,
u->pathname); u->pathname);
printf(" (%-*.*s %10s %*d) ", printf(" (%-*.*s %10s %*d) ",
longest_author, longest_author, ci.author, longest_author, longest_author, ci.author,
format_time(ci.author_time, ci.author_tz), format_time(ci.author_time, ci.author_tz,
show_raw_time),
max_digits, i+1); max_digits, i+1);
} }

View File

@ -51,6 +51,7 @@ int cmd_whatchanged(int argc, const char **argv, char **envp)
init_revisions(&rev); init_revisions(&rev);
rev.diff = 1; rev.diff = 1;
rev.diffopt.recursive = 1; rev.diffopt.recursive = 1;
rev.simplify_history = 0;
return cmd_log_wc(argc, argv, envp, &rev); return cmd_log_wc(argc, argv, envp, &rev);
} }
@ -112,7 +113,7 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject)
int len = 0; int len = 0;
if (output_directory) { if (output_directory) {
strncpy(filename, output_directory, 1010); safe_strncpy(filename, output_directory, 1010);
len = strlen(filename); len = strlen(filename);
if (filename[len - 1] != '/') if (filename[len - 1] != '/')
filename[len++] = '/'; filename[len++] = '/';

View File

@ -240,8 +240,8 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
/* XXX: should we provide more meaningful info here? */ /* XXX: should we provide more meaningful info here? */
sprintf(header.uid, "%07o", 0); sprintf(header.uid, "%07o", 0);
sprintf(header.gid, "%07o", 0); sprintf(header.gid, "%07o", 0);
strncpy(header.uname, "git", 31); safe_strncpy(header.uname, "git", sizeof(header.uname));
strncpy(header.gname, "git", 31); safe_strncpy(header.gname, "git", sizeof(header.gname));
sprintf(header.devmajor, "%07o", 0); sprintf(header.devmajor, "%07o", 0);
sprintf(header.devminor, "%07o", 0); sprintf(header.devminor, "%07o", 0);

View File

@ -216,7 +216,7 @@ enum sharedrepo {
int git_config_perm(const char *var, const char *value); int git_config_perm(const char *var, const char *value);
int adjust_shared_perm(const char *path); int adjust_shared_perm(const char *path);
int safe_create_leading_directories(char *path); int safe_create_leading_directories(char *path);
char *safe_strncpy(char *, const char *, size_t); size_t safe_strncpy(char *, const char *, size_t);
char *enter_repo(char *path, int strict); char *enter_repo(char *path, int strict);
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */ /* Read and unpack a sha1 file into memory, write memory to a sha1 file */

View File

@ -280,17 +280,17 @@ int git_default_config(const char *var, const char *value)
} }
if (!strcmp(var, "user.name")) { if (!strcmp(var, "user.name")) {
strncpy(git_default_name, value, sizeof(git_default_name)); safe_strncpy(git_default_name, value, sizeof(git_default_name));
return 0; return 0;
} }
if (!strcmp(var, "user.email")) { if (!strcmp(var, "user.email")) {
strncpy(git_default_email, value, sizeof(git_default_email)); safe_strncpy(git_default_email, value, sizeof(git_default_email));
return 0; return 0;
} }
if (!strcmp(var, "i18n.commitencoding")) { if (!strcmp(var, "i18n.commitencoding")) {
strncpy(git_commit_encoding, value, sizeof(git_commit_encoding)); safe_strncpy(git_commit_encoding, value, sizeof(git_commit_encoding));
return 0; return 0;
} }

View File

@ -29,8 +29,17 @@ git-svn.html : git-svn.txt
asciidoc -b xhtml11 -d manpage \ asciidoc -b xhtml11 -d manpage \
-f ../../Documentation/asciidoc.conf $< -f ../../Documentation/asciidoc.conf $<
test: git-svn test: git-svn
cd t && $(SHELL) ./t0000-contrib-git-svn.sh cd t && $(SHELL) ./t0000-contrib-git-svn.sh $(TEST_FLAGS)
cd t && $(SHELL) ./t0001-contrib-git-svn-props.sh cd t && $(SHELL) ./t0001-contrib-git-svn-props.sh $(TEST_FLAGS)
# we can test NO_OPTIMIZE_COMMITS independently of LC_ALL
full-test:
$(MAKE) test GIT_SVN_NO_LIB=1 GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C
$(MAKE) test GIT_SVN_NO_LIB=0 GIT_SVN_NO_OPTIMIZE_COMMITS=1 LC_ALL=C
$(MAKE) test GIT_SVN_NO_LIB=1 GIT_SVN_NO_OPTIMIZE_COMMITS=0 \
LC_ALL=en_US.UTF-8
$(MAKE) test GIT_SVN_NO_LIB=0 GIT_SVN_NO_OPTIMIZE_COMMITS=0 \
LC_ALL=en_US.UTF-8
clean: clean:
rm -f git-svn *.xml *.html *.1 rm -f git-svn *.xml *.html *.1

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,8 @@ fi
. ./test-lib.sh . ./test-lib.sh
GIT_DIR=$PWD/.git GIT_DIR=$PWD/.git
GIT_SVN_DIR=$GIT_DIR/git-svn GIT_SVN_DIR=$GIT_DIR/svn/git-svn
SVN_TREE=$GIT_SVN_DIR/tree SVN_TREE=$GIT_SVN_DIR/svn-tree
svnadmin >/dev/null 2>&1 svnadmin >/dev/null 2>&1
if test $? != 1 if test $? != 1

View File

@ -4,13 +4,17 @@
# #
test_description='git-svn tests' test_description='git-svn tests'
GIT_SVN_LC_ALL=$LC_ALL
. ./lib-git-svn.sh . ./lib-git-svn.sh
mkdir import mkdir import
cd import cd import
echo foo > foo echo foo > foo
ln -s foo foo.link if test -z "$NO_SYMLINK"
then
ln -s foo foo.link
fi
mkdir -p dir/a/b/c/d/e mkdir -p dir/a/b/c/d/e
echo 'deep dir' > dir/a/b/c/d/e/file echo 'deep dir' > dir/a/b/c/d/e/file
mkdir -p bar mkdir -p bar
@ -30,9 +34,10 @@ test_expect_success \
'import an SVN revision into git' \ 'import an SVN revision into git' \
'git-svn fetch' 'git-svn fetch'
test_expect_success "checkout from svn" "svn co $svnrepo $SVN_TREE"
name='try a deep --rmdir with a commit' name='try a deep --rmdir with a commit'
git checkout -b mybranch remotes/git-svn git checkout -f -b mybranch remotes/git-svn
mv dir/a/b/c/d/e/file dir/file mv dir/a/b/c/d/e/file dir/file
cp dir/file file cp dir/file file
git update-index --add --remove dir/a/b/c/d/e/file dir/file file git update-index --add --remove dir/a/b/c/d/e/file dir/file file
@ -40,6 +45,7 @@ git commit -m "$name"
test_expect_success "$name" \ test_expect_success "$name" \
"git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch && "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch &&
svn up $SVN_TREE &&
test -d $SVN_TREE/dir && test ! -d $SVN_TREE/dir/a" test -d $SVN_TREE/dir && test ! -d $SVN_TREE/dir/a"
@ -51,14 +57,14 @@ git update-index --remove dir/file
git update-index --add dir/file/file git update-index --add dir/file/file
git commit -m "$name" git commit -m "$name"
test_expect_code 1 "$name" \ test_expect_failure "$name" \
'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch' \ 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch' \
|| true || true
name='detect node change from directory to file #1' name='detect node change from directory to file #1'
rm -rf dir $GIT_DIR/index rm -rf dir $GIT_DIR/index
git checkout -b mybranch2 remotes/git-svn git checkout -f -b mybranch2 remotes/git-svn
mv bar/zzz zzz mv bar/zzz zzz
rm -rf bar rm -rf bar
mv zzz bar mv zzz bar
@ -66,14 +72,14 @@ git update-index --remove -- bar/zzz
git update-index --add -- bar git update-index --add -- bar
git commit -m "$name" git commit -m "$name"
test_expect_code 1 "$name" \ test_expect_failure "$name" \
'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch2' \ 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch2' \
|| true || true
name='detect node change from file to directory #2' name='detect node change from file to directory #2'
rm -f $GIT_DIR/index rm -f $GIT_DIR/index
git checkout -b mybranch3 remotes/git-svn git checkout -f -b mybranch3 remotes/git-svn
rm bar/zzz rm bar/zzz
git-update-index --remove bar/zzz git-update-index --remove bar/zzz
mkdir bar/zzz mkdir bar/zzz
@ -81,14 +87,14 @@ echo yyy > bar/zzz/yyy
git-update-index --add bar/zzz/yyy git-update-index --add bar/zzz/yyy
git commit -m "$name" git commit -m "$name"
test_expect_code 1 "$name" \ test_expect_failure "$name" \
'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch3' \ 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch3' \
|| true || true
name='detect node change from directory to file #2' name='detect node change from directory to file #2'
rm -f $GIT_DIR/index rm -f $GIT_DIR/index
git checkout -b mybranch4 remotes/git-svn git checkout -f -b mybranch4 remotes/git-svn
rm -rf dir rm -rf dir
git update-index --remove -- dir/file git update-index --remove -- dir/file
touch dir touch dir
@ -96,20 +102,21 @@ echo asdf > dir
git update-index --add -- dir git update-index --add -- dir
git commit -m "$name" git commit -m "$name"
test_expect_code 1 "$name" \ test_expect_failure "$name" \
'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch4' \ 'git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch4' \
|| true || true
name='remove executable bit from a file' name='remove executable bit from a file'
rm -f $GIT_DIR/index rm -f $GIT_DIR/index
git checkout -b mybranch5 remotes/git-svn git checkout -f -b mybranch5 remotes/git-svn
chmod -x exec.sh chmod -x exec.sh
git update-index exec.sh git update-index exec.sh
git commit -m "$name" git commit -m "$name"
test_expect_success "$name" \ test_expect_success "$name" \
"git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 &&
svn up $SVN_TREE &&
test ! -x $SVN_TREE/exec.sh" test ! -x $SVN_TREE/exec.sh"
@ -120,49 +127,64 @@ git commit -m "$name"
test_expect_success "$name" \ test_expect_success "$name" \
"git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 &&
svn up $SVN_TREE &&
test -x $SVN_TREE/exec.sh" test -x $SVN_TREE/exec.sh"
name='executable file becomes a symlink to bar/zzz (file)' if test -z "$NO_SYMLINK"
rm exec.sh then
ln -s bar/zzz exec.sh name='executable file becomes a symlink to bar/zzz (file)'
git update-index exec.sh rm exec.sh
git commit -m "$name" ln -s bar/zzz exec.sh
git update-index exec.sh
git commit -m "$name"
test_expect_success "$name" \ test_expect_success "$name" \
"git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 &&
test -L $SVN_TREE/exec.sh" svn up $SVN_TREE &&
test -L $SVN_TREE/exec.sh"
name='new symlink is added to a file that was also just made executable'
name='new symlink is added to a file that was also just made executable' chmod +x bar/zzz
chmod +x bar/zzz ln -s bar/zzz exec-2.sh
ln -s bar/zzz exec-2.sh git update-index --add bar/zzz exec-2.sh
git update-index --add bar/zzz exec-2.sh git commit -m "$name"
git commit -m "$name"
test_expect_success "$name" \
test_expect_success "$name" \ "git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 &&
"git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && svn up $SVN_TREE &&
test -x $SVN_TREE/bar/zzz && test -x $SVN_TREE/bar/zzz &&
test -L $SVN_TREE/exec-2.sh" test -L $SVN_TREE/exec-2.sh"
name='modify a symlink to become a file'
git help > help || true
name='modify a symlink to become a file' rm exec-2.sh
git help > help || true cp help exec-2.sh
rm exec-2.sh git update-index exec-2.sh
cp help exec-2.sh git commit -m "$name"
git update-index exec-2.sh
git commit -m "$name" test_expect_success "$name" \
"git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 &&
test_expect_success "$name" \ svn up $SVN_TREE &&
"git-svn commit --find-copies-harder --rmdir remotes/git-svn..mybranch5 && test -f $SVN_TREE/exec-2.sh &&
test -f $SVN_TREE/exec-2.sh && test ! -L $SVN_TREE/exec-2.sh &&
test ! -L $SVN_TREE/exec-2.sh && diff -u help $SVN_TREE/exec-2.sh"
diff -u help $SVN_TREE/exec-2.sh" fi
if test -n "$GIT_SVN_LC_ALL" && echo $GIT_SVN_LC_ALL | grep -q '\.UTF-8$'
then
name="commit with UTF-8 message: locale: $GIT_SVN_LC_ALL"
echo '# hello' >> exec-2.sh
git update-index exec-2.sh
git commit -m 'éï∏'
export LC_ALL="$GIT_SVN_LC_ALL"
test_expect_success "$name" "git-svn commit HEAD"
unset LC_ALL
else
echo "UTF-8 locale not set, test skipped ($GIT_SVN_LC_ALL)"
fi
name='test fetch functionality (svn => git) with alternate GIT_SVN_ID' name='test fetch functionality (svn => git) with alternate GIT_SVN_ID'
GIT_SVN_ID=alt GIT_SVN_ID=alt
@ -173,5 +195,28 @@ test_expect_success "$name" \
git-rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b && git-rev-list --pretty=raw remotes/alt | grep ^tree | uniq > b &&
diff -u a b" diff -u a b"
if test -n "$NO_SYMLINK"
then
test_done
exit 0
fi
name='check imported tree checksums expected tree checksums'
rm -f expected
if test -n "$GIT_SVN_LC_ALL" && echo $GIT_SVN_LC_ALL | grep -q '\.UTF-8$'
then
echo tree f735671b89a7eb30cab1d8597de35bd4271ab813 > expected
fi
cat >> expected <<\EOF
tree 4b9af72bb861eaed053854ec502cf7df72618f0f
tree 031b8d557afc6fea52894eaebb45bec52f1ba6d1
tree 0b094cbff17168f24c302e297f55bfac65eb8bd3
tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e
tree 56a30b966619b863674f5978696f4a3594f2fca9
tree d667270a1f7b109f5eb3aaea21ede14b56bfdd6e
tree 8f51f74cf0163afc9ad68a4b1537288c4558b5a4
EOF
test_expect_success "$name" "diff -u a expected"
test_done test_done

View File

@ -52,49 +52,49 @@ EOF
cd .. cd ..
rm -rf import rm -rf import
svn co "$svnrepo" test_wc test_expect_success 'checkout working copy from svn' "svn co $svnrepo test_wc"
test_expect_success 'setup some commits to svn' \
'cd test_wc &&
echo Greetings >> kw.c &&
svn commit -m "Not yet an Id" &&
svn up &&
echo Hello world >> kw.c &&
svn commit -m "Modified file, but still not yet an Id" &&
svn up &&
svn propset svn:keywords Id kw.c &&
svn commit -m "Propset Id" &&
svn up &&
cd ..'
cd test_wc test_expect_success 'initialize git-svn' "git-svn init $svnrepo"
echo 'Greetings' >> kw.c test_expect_success 'fetch revisions from svn' 'git-svn fetch'
svn commit -m 'Not yet an $Id$'
svn up
echo 'Hello world' >> kw.c
svn commit -m 'Modified file, but still not yet an $Id$'
svn up
svn propset svn:keywords Id kw.c
svn commit -m 'Propset $Id$'
svn up
cd ..
git-svn init "$svnrepo"
git-svn fetch
git checkout -b mybranch remotes/git-svn
echo 'Hi again' >> kw.c
name='test svn:keywords ignoring' name='test svn:keywords ignoring'
test_expect_success "$name" \
git commit -a -m "$name" 'git checkout -b mybranch remotes/git-svn &&
git-svn commit remotes/git-svn..mybranch echo Hi again >> kw.c &&
git pull . remotes/git-svn git commit -a -m "test keywoards ignoring" &&
git-svn commit remotes/git-svn..mybranch &&
git pull . remotes/git-svn'
expect='/* $Id$ */' expect='/* $Id$ */'
got="`sed -ne 2p kw.c`" got="`sed -ne 2p kw.c`"
test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'" test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'"
cd test_wc test_expect_success "propset CR on crlf files" \
svn propset svn:eol-style CR empty 'cd test_wc &&
svn propset svn:eol-style CR crlf svn propset svn:eol-style CR empty &&
svn propset svn:eol-style CR ne_crlf svn propset svn:eol-style CR crlf &&
svn commit -m 'propset CR on crlf files' svn propset svn:eol-style CR ne_crlf &&
svn up svn commit -m "propset CR on crlf files" &&
cd .. svn up &&
cd ..'
git-svn fetch test_expect_success 'fetch and pull latest from svn and checkout a new wc' \
git pull . remotes/git-svn "git-svn fetch &&
git pull . remotes/git-svn &&
svn co $svnrepo new_wc"
svn co "$svnrepo" new_wc
for i in crlf ne_crlf lf ne_lf cr ne_cr empty_cr empty_lf empty empty_crlf for i in crlf ne_crlf lf ne_lf cr ne_cr empty_cr empty_lf empty empty_crlf
do do
test_expect_success "Comparing $i" "cmp $i new_wc/$i" test_expect_success "Comparing $i" "cmp $i new_wc/$i"
@ -106,16 +106,16 @@ cd test_wc
printf '$Id$\rHello\rWorld' > ne_cr printf '$Id$\rHello\rWorld' > ne_cr
a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git-hash-object --stdin` a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git-hash-object --stdin`
a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git-hash-object --stdin` a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git-hash-object --stdin`
svn propset svn:eol-style CRLF cr test_expect_success 'Set CRLF on cr files' \
svn propset svn:eol-style CRLF ne_cr 'svn propset svn:eol-style CRLF cr &&
svn propset svn:keywords Id cr svn propset svn:eol-style CRLF ne_cr &&
svn propset svn:keywords Id ne_cr svn propset svn:keywords Id cr &&
svn commit -m 'propset CRLF on cr files' svn propset svn:keywords Id ne_cr &&
svn up svn commit -m "propset CRLF on cr files" &&
svn up'
cd .. cd ..
test_expect_success 'fetch and pull latest from svn' \
git-svn fetch 'git-svn fetch && git pull . remotes/git-svn'
git pull . remotes/git-svn
b_cr="`git-hash-object cr`" b_cr="`git-hash-object cr`"
b_ne_cr="`git-hash-object ne_cr`" b_ne_cr="`git-hash-object ne_cr`"

79
diff.c
View File

@ -25,6 +25,20 @@ int git_diff_config(const char *var, const char *value)
return git_default_config(var, value); return git_default_config(var, value);
} }
enum color_diff {
DIFF_PLAIN = 0,
DIFF_METAINFO = 1,
DIFF_FILE_OLD = 2,
DIFF_FILE_NEW = 3,
};
static const char *diff_colors[] = {
"\033[0;0m",
"\033[1;35m",
"\033[1;31m",
"\033[1;34m",
};
static char *quote_one(const char *str) static char *quote_one(const char *str)
{ {
int needlen; int needlen;
@ -177,23 +191,54 @@ static int fill_mmfile(mmfile_t *mf, struct diff_filespec *one)
} }
struct emit_callback { struct emit_callback {
struct xdiff_emit_state xm;
int nparents, color_diff;
const char **label_path; const char **label_path;
}; };
static int fn_out(void *priv, mmbuffer_t *mb, int nbuf) static inline void color_diff(int diff_use_color, enum color_diff ix)
{
if (diff_use_color)
fputs(diff_colors[ix], stdout);
}
static void fn_out_consume(void *priv, char *line, unsigned long len)
{ {
int i; int i;
struct emit_callback *ecbdata = priv; struct emit_callback *ecbdata = priv;
if (ecbdata->label_path[0]) { if (ecbdata->label_path[0]) {
color_diff(ecbdata->color_diff, DIFF_METAINFO);
printf("--- %s\n", ecbdata->label_path[0]); printf("--- %s\n", ecbdata->label_path[0]);
color_diff(ecbdata->color_diff, DIFF_METAINFO);
printf("+++ %s\n", ecbdata->label_path[1]); printf("+++ %s\n", ecbdata->label_path[1]);
ecbdata->label_path[0] = ecbdata->label_path[1] = NULL; ecbdata->label_path[0] = ecbdata->label_path[1] = NULL;
} }
for (i = 0; i < nbuf; i++)
if (!fwrite(mb[i].ptr, mb[i].size, 1, stdout)) /* This is not really necessary for now because
return -1; * this codepath only deals with two-way diffs.
return 0; */
for (i = 0; i < len && line[i] == '@'; i++)
;
if (2 <= i && i < len && line[i] == ' ') {
ecbdata->nparents = i - 1;
color_diff(ecbdata->color_diff, DIFF_METAINFO);
}
else if (len < ecbdata->nparents)
color_diff(ecbdata->color_diff, DIFF_PLAIN);
else {
int nparents = ecbdata->nparents;
int color = DIFF_PLAIN;
for (i = 0; i < nparents && len; i++) {
if (line[i] == '-')
color = DIFF_FILE_OLD;
else if (line[i] == '+')
color = DIFF_FILE_NEW;
}
color_diff(ecbdata->color_diff, color);
}
fwrite(line, len, 1, stdout);
color_diff(ecbdata->color_diff, DIFF_PLAIN);
} }
static char *pprint_rename(const char *a, const char *b) static char *pprint_rename(const char *a, const char *b)
@ -549,25 +594,35 @@ static void builtin_diff(const char *name_a,
b_two = quote_two("b/", name_b); b_two = quote_two("b/", name_b);
lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null"; lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null"; lbl[1] = DIFF_FILE_VALID(two) ? b_two : "/dev/null";
color_diff(o->color_diff, DIFF_METAINFO);
printf("diff --git %s %s\n", a_one, b_two); printf("diff --git %s %s\n", a_one, b_two);
if (lbl[0][0] == '/') { if (lbl[0][0] == '/') {
/* /dev/null */ /* /dev/null */
color_diff(o->color_diff, DIFF_METAINFO);
printf("new file mode %06o\n", two->mode); printf("new file mode %06o\n", two->mode);
if (xfrm_msg && xfrm_msg[0]) if (xfrm_msg && xfrm_msg[0]) {
color_diff(o->color_diff, DIFF_METAINFO);
puts(xfrm_msg); puts(xfrm_msg);
}
} }
else if (lbl[1][0] == '/') { else if (lbl[1][0] == '/') {
printf("deleted file mode %06o\n", one->mode); printf("deleted file mode %06o\n", one->mode);
if (xfrm_msg && xfrm_msg[0]) if (xfrm_msg && xfrm_msg[0]) {
color_diff(o->color_diff, DIFF_METAINFO);
puts(xfrm_msg); puts(xfrm_msg);
}
} }
else { else {
if (one->mode != two->mode) { if (one->mode != two->mode) {
color_diff(o->color_diff, DIFF_METAINFO);
printf("old mode %06o\n", one->mode); printf("old mode %06o\n", one->mode);
color_diff(o->color_diff, DIFF_METAINFO);
printf("new mode %06o\n", two->mode); printf("new mode %06o\n", two->mode);
} }
if (xfrm_msg && xfrm_msg[0]) if (xfrm_msg && xfrm_msg[0]) {
color_diff(o->color_diff, DIFF_METAINFO);
puts(xfrm_msg); puts(xfrm_msg);
}
/* /*
* we do not run diff between different kind * we do not run diff between different kind
* of objects. * of objects.
@ -575,6 +630,7 @@ static void builtin_diff(const char *name_a,
if ((one->mode ^ two->mode) & S_IFMT) if ((one->mode ^ two->mode) & S_IFMT)
goto free_ab_and_return; goto free_ab_and_return;
if (complete_rewrite) { if (complete_rewrite) {
color_diff(o->color_diff, DIFF_PLAIN);
emit_rewrite_diff(name_a, name_b, one, two); emit_rewrite_diff(name_a, name_b, one, two);
goto free_ab_and_return; goto free_ab_and_return;
} }
@ -602,7 +658,9 @@ static void builtin_diff(const char *name_a,
xdemitcb_t ecb; xdemitcb_t ecb;
struct emit_callback ecbdata; struct emit_callback ecbdata;
memset(&ecbdata, 0, sizeof(ecbdata));
ecbdata.label_path = lbl; ecbdata.label_path = lbl;
ecbdata.color_diff = o->color_diff;
xpp.flags = XDF_NEED_MINIMAL; xpp.flags = XDF_NEED_MINIMAL;
xecfg.ctxlen = o->context; xecfg.ctxlen = o->context;
xecfg.flags = XDL_EMIT_FUNCNAMES; xecfg.flags = XDL_EMIT_FUNCNAMES;
@ -612,8 +670,9 @@ static void builtin_diff(const char *name_a,
xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10); xecfg.ctxlen = strtoul(diffopts + 10, NULL, 10);
else if (!strncmp(diffopts, "-u", 2)) else if (!strncmp(diffopts, "-u", 2))
xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10); xecfg.ctxlen = strtoul(diffopts + 2, NULL, 10);
ecb.outf = fn_out; ecb.outf = xdiff_outf;
ecb.priv = &ecbdata; ecb.priv = &ecbdata;
ecbdata.xm.consume = fn_out_consume;
xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb); xdl_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
} }
@ -1456,6 +1515,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
else if (40 < options->abbrev) else if (40 < options->abbrev)
options->abbrev = 40; options->abbrev = 40;
} }
else if (!strcmp(arg, "--color"))
options->color_diff = 1;
else else
return 0; return 0;
return 1; return 1;

3
diff.h
View File

@ -32,7 +32,8 @@ struct diff_options {
full_index:1, full_index:1,
silent_on_remove:1, silent_on_remove:1,
find_copies_harder:1, find_copies_harder:1,
summary:1; summary:1,
color_diff:1;
int context; int context;
int break_opt; int break_opt;
int detect_rename; int detect_rename;

View File

@ -134,7 +134,7 @@ foreach my $f (@afiles) {
and $status[0] !~ m/^File: no file /) { and $status[0] !~ m/^File: no file /) {
$dirty = 1; $dirty = 1;
warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n"; warn "File $f is already known in your CVS checkout -- perhaps it has been added by another user. Or this may indicate that it exists on a different branch. If this is the case, use -f to force the merge.\n";
warn "Status was: $status\n"; warn "Status was: $status[0]\n";
} }
} }
foreach my $f (@mfiles, @dfiles) { foreach my $f (@mfiles, @dfiles) {

96
git-cvsimport.perl Executable file → Normal file
View File

@ -465,10 +465,15 @@ $git_dir = getwd()."/".$git_dir unless $git_dir =~ m#^/#;
$ENV{"GIT_DIR"} = $git_dir; $ENV{"GIT_DIR"} = $git_dir;
my $orig_git_index; my $orig_git_index;
$orig_git_index = $ENV{GIT_INDEX_FILE} if exists $ENV{GIT_INDEX_FILE}; $orig_git_index = $ENV{GIT_INDEX_FILE} if exists $ENV{GIT_INDEX_FILE};
my ($git_ih, $git_index) = tempfile('gitXXXXXX', SUFFIX => '.idx',
DIR => File::Spec->tmpdir()); my %index; # holds filenames of one index per branch
close ($git_ih); { # init with an index for origin
$ENV{GIT_INDEX_FILE} = $git_index; my ($fh, $fn) = tempfile('gitXXXXXX', SUFFIX => '.idx',
DIR => File::Spec->tmpdir());
close ($fh);
$index{$opt_o} = $fn;
}
$ENV{GIT_INDEX_FILE} = $index{$opt_o};
unless(-d $git_dir) { unless(-d $git_dir) {
system("git-init-db"); system("git-init-db");
die "Cannot init the GIT db at $git_tree: $?\n" if $?; die "Cannot init the GIT db at $git_tree: $?\n" if $?;
@ -496,6 +501,13 @@ unless(-d $git_dir) {
$tip_at_start = `git-rev-parse --verify HEAD`; $tip_at_start = `git-rev-parse --verify HEAD`;
# populate index # populate index
unless ($index{$last_branch}) {
my ($fh, $fn) = tempfile('gitXXXXXX', SUFFIX => '.idx',
DIR => File::Spec->tmpdir());
close ($fh);
$index{$last_branch} = $fn;
}
$ENV{GIT_INDEX_FILE} = $index{$last_branch};
system('git-read-tree', $last_branch); system('git-read-tree', $last_branch);
die "read-tree failed: $?\n" if $?; die "read-tree failed: $?\n" if $?;
@ -529,25 +541,39 @@ if ($opt_A) {
write_author_info("$git_dir/cvs-authors"); write_author_info("$git_dir/cvs-authors");
} }
my $pid = open(CVS,"-|");
die "Cannot fork: $!\n" unless defined $pid; #
unless($pid) { # run cvsps into a file unless we are getting
my @opt; # it passed as a file via $opt_P
@opt = split(/,/,$opt_p) if defined $opt_p; #
unshift @opt, '-z', $opt_z if defined $opt_z; unless ($opt_P) {
unshift @opt, '-q' unless defined $opt_v; print "Running cvsps...\n" if $opt_v;
unless (defined($opt_p) && $opt_p =~ m/--no-cvs-direct/) { my $pid = open(CVSPS,"-|");
push @opt, '--cvs-direct'; die "Cannot fork: $!\n" unless defined $pid;
unless($pid) {
my @opt;
@opt = split(/,/,$opt_p) if defined $opt_p;
unshift @opt, '-z', $opt_z if defined $opt_z;
unshift @opt, '-q' unless defined $opt_v;
unless (defined($opt_p) && $opt_p =~ m/--no-cvs-direct/) {
push @opt, '--cvs-direct';
}
exec("cvsps","--norc",@opt,"-u","-A",'--root',$opt_d,$cvs_tree);
die "Could not start cvsps: $!\n";
} }
if ($opt_P) { my ($cvspsfh, $cvspsfile) = tempfile('gitXXXXXX', SUFFIX => '.cvsps',
exec("cat", $opt_P); DIR => File::Spec->tmpdir());
} else { while (<CVSPS>) {
exec("cvsps","--norc",@opt,"-u","-A",'--root',$opt_d,$cvs_tree); print $cvspsfh $_;
die "Could not start cvsps: $!\n";
} }
close CVSPS;
close $cvspsfh;
$opt_P = $cvspsfile;
} }
open(CVS, "<$opt_P") or die $!;
## cvsps output: ## cvsps output:
#--------------------- #---------------------
#PatchSet 314 #PatchSet 314
@ -595,7 +621,11 @@ sub write_tree () {
} }
my($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg); my($patchset,$date,$author_name,$author_email,$branch,$ancestor,$tag,$logmsg);
my(@old,@new,@skipped); my(@old,@new,@skipped,%ignorebranch);
# commits that cvsps cannot place anywhere...
$ignorebranch{'#CVSPS_NO_BRANCH'} = 1;
sub commit { sub commit {
update_index(@old, @new); update_index(@old, @new);
@old = @new = (); @old = @new = ();
@ -751,7 +781,16 @@ while(<CVS>) {
$state = 11; $state = 11;
next; next;
} }
if (exists $ignorebranch{$branch}) {
print STDERR "Skipping $branch\n";
$state = 11;
next;
}
if($ancestor) { if($ancestor) {
if($ancestor eq $branch) {
print STDERR "Branch $branch erroneously stems from itself -- changed ancestor to $opt_o\n";
$ancestor = $opt_o;
}
if(-f "$git_dir/refs/heads/$branch") { if(-f "$git_dir/refs/heads/$branch") {
print STDERR "Branch $branch already exists!\n"; print STDERR "Branch $branch already exists!\n";
$state=11; $state=11;
@ -759,6 +798,7 @@ while(<CVS>) {
} }
unless(open(H,"$git_dir/refs/heads/$ancestor")) { unless(open(H,"$git_dir/refs/heads/$ancestor")) {
print STDERR "Branch $ancestor does not exist!\n"; print STDERR "Branch $ancestor does not exist!\n";
$ignorebranch{$branch} = 1;
$state=11; $state=11;
next; next;
} }
@ -766,6 +806,7 @@ while(<CVS>) {
close(H); close(H);
unless(open(H,"> $git_dir/refs/heads/$branch")) { unless(open(H,"> $git_dir/refs/heads/$branch")) {
print STDERR "Could not create branch $branch: $!\n"; print STDERR "Could not create branch $branch: $!\n";
$ignorebranch{$branch} = 1;
$state=11; $state=11;
next; next;
} }
@ -776,8 +817,17 @@ while(<CVS>) {
} }
if(($ancestor || $branch) ne $last_branch) { if(($ancestor || $branch) ne $last_branch) {
print "Switching from $last_branch to $branch\n" if $opt_v; print "Switching from $last_branch to $branch\n" if $opt_v;
system("git-read-tree", $branch); unless ($index{$branch}) {
die "read-tree failed: $?\n" if $?; my ($fh, $fn) = tempfile('gitXXXXXX', SUFFIX => '.idx',
DIR => File::Spec->tmpdir());
close ($fh);
$index{$branch} = $fn;
$ENV{GIT_INDEX_FILE} = $index{$branch};
system("git-read-tree", $branch);
die "read-tree failed: $?\n" if $?;
} else {
$ENV{GIT_INDEX_FILE} = $index{$branch};
}
} }
$last_branch = $branch if $branch ne $last_branch; $last_branch = $branch if $branch ne $last_branch;
$state = 9; $state = 9;
@ -841,7 +891,9 @@ while(<CVS>) {
} }
commit() if $branch and $state != 11; commit() if $branch and $state != 11;
unlink($git_index); foreach my $git_index (values %index) {
unlink($git_index);
}
if (defined $orig_git_index) { if (defined $orig_git_index) {
$ENV{GIT_INDEX_FILE} = $orig_git_index; $ENV{GIT_INDEX_FILE} = $orig_git_index;

View File

@ -23,7 +23,6 @@ s = signal(SIGINT, SIG_DFL)
if s != default_int_handler: if s != default_int_handler:
signal(SIGINT, s) signal(SIGINT, s)
def die(msg, *args): def die(msg, *args):
for a in args: for a in args:
msg = "%s %s" % (msg, a) msg = "%s %s" % (msg, a)
@ -38,6 +37,7 @@ verbosity = 1
logfile = "/dev/null" logfile = "/dev/null"
ignore_warnings = False ignore_warnings = False
stitch = 0 stitch = 0
tagall = True
def report(level, msg, *args): def report(level, msg, *args):
global verbosity global verbosity
@ -261,10 +261,9 @@ class git_command:
self.make_tag("p4/%s"%id, commit) self.make_tag("p4/%s"%id, commit)
self.git("update-ref HEAD %s %s" % (commit, current) ) self.git("update-ref HEAD %s %s" % (commit, current) )
try: try:
opts, args = getopt.getopt(sys.argv[1:], "qhvt:", opts, args = getopt.getopt(sys.argv[1:], "qhvt:",
["authors=","help","stitch=","timezone=","log=","ignore"]) ["authors=","help","stitch=","timezone=","log=","ignore","notags"])
except getopt.GetoptError: except getopt.GetoptError:
usage() usage()
@ -275,6 +274,8 @@ for o, a in opts:
verbosity += 1 verbosity += 1
if o in ("--log"): if o in ("--log"):
logfile = a logfile = a
if o in ("--notags"):
tagall = False
if o in ("-h", "--help"): if o in ("-h", "--help"):
usage() usage()
if o in ("--ignore"): if o in ("--ignore"):
@ -350,7 +351,10 @@ for id in changes:
report(1, "Importing changeset", id) report(1, "Importing changeset", id)
change = p4.describe(id) change = p4.describe(id)
p4.sync(id) p4.sync(id)
git.commit(change.author, change.email, change.date, change.msg, id) if tagall :
git.commit(change.author, change.email, change.date, change.msg, id)
else:
git.commit(change.author, change.email, change.date, change.msg, "import")
if stitch == 1: if stitch == 1:
git.clean_directories() git.clean_directories()
stitch = 0 stitch = 0

6
git.c
View File

@ -122,9 +122,9 @@ static int handle_alias(int *argcp, const char ***argv)
/* insert after command name */ /* insert after command name */
if (*argcp > 1) { if (*argcp > 1) {
new_argv = realloc(new_argv, sizeof(char*) * new_argv = realloc(new_argv, sizeof(char*) *
(count + *argcp - 1)); (count + *argcp));
memcpy(new_argv + count, *argv, sizeof(char*) * memcpy(new_argv + count, *argv + 1,
(*argcp - 1)); sizeof(char*) * *argcp);
} }
*argv = new_argv; *argv = new_argv;

18
gitk
View File

@ -5196,6 +5196,24 @@ proc rereadrefs {} {
} }
} }
proc listrefs {id} {
global idtags idheads idotherrefs
set x {}
if {[info exists idtags($id)]} {
set x $idtags($id)
}
set y {}
if {[info exists idheads($id)]} {
set y $idheads($id)
}
set z {}
if {[info exists idotherrefs($id)]} {
set z $idotherrefs($id)
}
return [list $x $y $z]
}
proc showtag {tag isnew} { proc showtag {tag isnew} {
global ctext tagcontents tagids linknum global ctext tagcontents tagids linknum

View File

@ -3,14 +3,7 @@ GIT web Interface
The one working on: The one working on:
http://www.kernel.org/git/ http://www.kernel.org/git/
Get the gitweb.cgi by ftp: From the git version 1.4.0 gitweb is bundled with git.
ftp://ftp.kernel.org/pub/software/scm/gitweb/
It reqires the git-core binaries installed on the system:
http://www.kernel.org/git/?p=git/git.git;a=summary
The gitweb repository is here:
http://www.kernel.org/git/?p=git/gitweb.git;a=summary
Any comment/question/concern to: Any comment/question/concern to:
Kay Sievers <kay.sievers@vrfy.org> Kay Sievers <kay.sievers@vrfy.org>

View File

@ -203,6 +203,9 @@ if (!defined $action || $action eq "summary") {
} elsif ($action eq "tag") { } elsif ($action eq "tag") {
git_tag(); git_tag();
exit; exit;
} elsif ($action eq "blame") {
git_blame();
exit;
} else { } else {
undef $action; undef $action;
die_error(undef, "Unknown action."); die_error(undef, "Unknown action.");
@ -834,6 +837,25 @@ sub git_read_projects {
return @list; return @list;
} }
sub git_get_project_config {
my $key = shift;
return unless ($key);
$key =~ s/^gitweb\.//;
return if ($key =~ m/\W/);
my $val = qx(git-repo-config --get gitweb.$key);
return ($val);
}
sub git_get_project_config_bool {
my $val = git_get_project_config (@_);
if ($val and $val =~ m/true|yes|on/) {
return (1);
}
return; # implicit false
}
sub git_project_list { sub git_project_list {
my @list = git_read_projects(); my @list = git_read_projects();
my @projects; my @projects;
@ -1228,6 +1250,108 @@ sub git_tag {
git_footer_html(); git_footer_html();
} }
sub git_blame {
my $fd;
die_error('403 Permission denied', "Permission denied.") if (!git_get_project_config_bool ('blame'));
die_error('404 Not Found', "What file will it be, master?") if (!$file_name);
$hash_base ||= git_read_head($project);
die_error(undef, "Reading commit failed.") unless ($hash_base);
my %co = git_read_commit($hash_base)
or die_error(undef, "Reading commit failed.");
if (!defined $hash) {
$hash = git_get_hash_by_path($hash_base, $file_name, "blob")
or die_error(undef, "Error lookup file.");
}
open ($fd, "-|", "$gitbin/git-annotate", '-l', '-t', '-r', $file_name, $hash_base)
or die_error(undef, "Open failed.");
git_header_html();
print "<div class=\"page_nav\">\n" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base")}, "commit") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "<br/>\n";
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$hash;hb=$hash_base;f=$file_name")}, "blob") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;f=$file_name")}, "head") . "<br/>\n";
print "</div>\n".
"<div>" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'})) .
"</div>\n";
print "<div class=\"page_path\"><b>" . esc_html($file_name) . "</b></div>\n";
print "<div class=\"page_body\">\n";
print <<HTML;
<table style="border-collapse: collapse;">
<tr>
<th>Commit</th>
<th>Age</th>
<th>Author</th>
<th>Line</th>
<th>Data</th>
</tr>
HTML
my @line_class = (qw(light dark));
my $line_class_len = scalar (@line_class);
my $line_class_num = $#line_class;
while (my $line = <$fd>) {
my $long_rev;
my $short_rev;
my $author;
my $time;
my $lineno;
my $data;
my $age;
my $age_str;
my $age_style;
chomp $line;
$line_class_num = ($line_class_num + 1) % $line_class_len;
if ($line =~ m/^([0-9a-fA-F]{40})\t\(\s*([^\t]+)\t(\d+) \+\d\d\d\d\t(\d+)\)(.*)$/) {
$long_rev = $1;
$author = $2;
$time = $3;
$lineno = $4;
$data = $5;
} else {
print qq( <tr><td colspan="5" style="color: red; background-color: yellow;">Unable to parse: $line</td></tr>\n);
next;
}
$short_rev = substr ($long_rev, 0, 8);
$age = time () - $time;
$age_str = age_string ($age);
$age_str =~ s/ /&nbsp;/g;
$age_style = 'font-style: italic;';
$age_style .= ' color: #009900; background: transparent;' if ($age < 60*60*24*2);
$age_style .= ' font-weight: bold;' if ($age < 60*60*2);
$author = esc_html ($author);
$author =~ s/ /&nbsp;/g;
# escape tabs
while ((my $pos = index($data, "\t")) != -1) {
if (my $count = (8 - ($pos % 8))) {
my $spaces = ' ' x $count;
$data =~ s/\t/$spaces/;
}
}
$data = esc_html ($data);
$data =~ s/ /&nbsp;/g;
print <<HTML;
<tr class="$line_class[$line_class_num]">
<td style="font-family: monospace;"><a href="$my_uri?${\esc_param ("p=$project;a=commit;h=$long_rev")}" class="text">$short_rev..</a></td>
<td style="$age_style">$age_str</td>
<td>$author</td>
<td style="text-align: right;"><a id="$lineno" href="#$lineno" class="linenr">$lineno</a></td>
<td style="font-family: monospace;">$data</td>
</tr>
HTML
} # while (my $line = <$fd>)
print "</table>\n\n";
close $fd or print "Reading blob failed.\n";
print "</div>";
git_footer_html();
}
sub git_tags { sub git_tags {
my $head = git_read_head($project); my $head = git_read_head($project);
git_header_html(); git_header_html();
@ -1364,6 +1488,7 @@ sub git_blob {
my $base = $hash_base || git_read_head($project); my $base = $hash_base || git_read_head($project);
$hash = git_get_hash_by_path($base, $file_name, "blob") || die_error(undef, "Error lookup file."); $hash = git_get_hash_by_path($base, $file_name, "blob") || die_error(undef, "Error lookup file.");
} }
my $have_blame = git_get_project_config_bool ('blame');
open my $fd, "-|", "$gitbin/git-cat-file blob $hash" or die_error(undef, "Open failed."); open my $fd, "-|", "$gitbin/git-cat-file blob $hash" or die_error(undef, "Open failed.");
git_header_html(); git_header_html();
if (defined $hash_base && (my %co = git_read_commit($hash_base))) { if (defined $hash_base && (my %co = git_read_commit($hash_base))) {
@ -1375,6 +1500,9 @@ sub git_blob {
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "<br/>\n"; " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "<br/>\n";
if (defined $file_name) { if (defined $file_name) {
if ($have_blame) {
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;h=$hash;hb=$hash_base;f=$file_name")}, "blame") . " | ";
}
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$hash;f=$file_name")}, "plain") . print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$hash;f=$file_name")}, "plain") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;hb=HEAD;f=$file_name")}, "head") . "<br/>\n"; " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;hb=HEAD;f=$file_name")}, "head") . "<br/>\n";
} else { } else {
@ -1496,6 +1624,7 @@ sub git_tree {
"</td>\n" . "</td>\n" .
"<td class=\"link\">" . "<td class=\"link\">" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name")}, "blob") . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name")}, "blob") .
# " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;h=$t_hash$base_key;f=$base$t_name")}, "blame") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash_base;f=$base$t_name")}, "history") . " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash_base;f=$base$t_name")}, "history") .
"</td>\n"; "</td>\n";
} elsif ($t_type eq "tree") { } elsif ($t_type eq "tree") {

View File

@ -584,10 +584,8 @@ static void process_alternates_response(void *callback_data)
// skip 'objects' at end // skip 'objects' at end
if (okay) { if (okay) {
target = xmalloc(serverlen + posn - i - 6); target = xmalloc(serverlen + posn - i - 6);
strncpy(target, base, serverlen); safe_strncpy(target, base, serverlen);
strncpy(target + serverlen, data + i, safe_strncpy(target + serverlen, data + i, posn - i - 6);
posn - i - 7);
target[serverlen + posn - i - 7] = '\0';
if (get_verbosely) if (get_verbosely)
fprintf(stderr, fprintf(stderr,
"Also look at %s\n", target); "Also look at %s\n", target);
@ -728,8 +726,8 @@ xml_cdata(void *userData, const XML_Char *s, int len)
struct xml_ctx *ctx = (struct xml_ctx *)userData; struct xml_ctx *ctx = (struct xml_ctx *)userData;
if (ctx->cdata) if (ctx->cdata)
free(ctx->cdata); free(ctx->cdata);
ctx->cdata = xcalloc(len+1, 1); ctx->cdata = xmalloc(len + 1);
strncpy(ctx->cdata, s, len); safe_strncpy(ctx->cdata, s, len + 1);
} }
static int remote_ls(struct alt_base *repo, const char *path, int flags, static int remote_ls(struct alt_base *repo, const char *path, int flags,

View File

@ -1269,8 +1269,8 @@ xml_cdata(void *userData, const XML_Char *s, int len)
struct xml_ctx *ctx = (struct xml_ctx *)userData; struct xml_ctx *ctx = (struct xml_ctx *)userData;
if (ctx->cdata) if (ctx->cdata)
free(ctx->cdata); free(ctx->cdata);
ctx->cdata = xcalloc(len+1, 1); ctx->cdata = xmalloc(len + 1);
strncpy(ctx->cdata, s, len); safe_strncpy(ctx->cdata, s, len + 1);
} }
static struct remote_lock *lock_remote(char *path, long timeout) static struct remote_lock *lock_remote(char *path, long timeout)
@ -1472,7 +1472,7 @@ static void process_ls_object(struct remote_ls_ctx *ls)
return; return;
path += 8; path += 8;
obj_hex = xmalloc(strlen(path)); obj_hex = xmalloc(strlen(path));
strncpy(obj_hex, path, 2); safe_strncpy(obj_hex, path, 3);
strcpy(obj_hex + 2, path + 3); strcpy(obj_hex + 2, path + 3);
one_remote_object(obj_hex); one_remote_object(obj_hex);
free(obj_hex); free(obj_hex);
@ -2160,8 +2160,8 @@ static void fetch_symref(char *path, char **symref, unsigned char *sha1)
/* If it's a symref, set the refname; otherwise try for a sha1 */ /* If it's a symref, set the refname; otherwise try for a sha1 */
if (!strncmp((char *)buffer.buffer, "ref: ", 5)) { if (!strncmp((char *)buffer.buffer, "ref: ", 5)) {
*symref = xcalloc(buffer.posn - 5, 1); *symref = xmalloc(buffer.posn - 5);
strncpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 6); safe_strncpy(*symref, (char *)buffer.buffer + 5, buffer.posn - 5);
} else { } else {
get_sha1_hex(buffer.buffer, sha1); get_sha1_hex(buffer.buffer, sha1);
} }

View File

@ -71,10 +71,9 @@ int setup_ident(void)
len = strlen(git_default_email); len = strlen(git_default_email);
git_default_email[len++] = '.'; git_default_email[len++] = '.';
if (he && (domainname = strchr(he->h_name, '.'))) if (he && (domainname = strchr(he->h_name, '.')))
strncpy(git_default_email + len, domainname + 1, sizeof(git_default_email) - len); safe_strncpy(git_default_email + len, domainname + 1, sizeof(git_default_email) - len);
else else
strncpy(git_default_email + len, "(none)", sizeof(git_default_email) - len); safe_strncpy(git_default_email + len, "(none)", sizeof(git_default_email) - len);
git_default_email[sizeof(git_default_email) - 1] = 0;
} }
/* And set the default date */ /* And set the default date */
datestamp(git_default_date, sizeof(git_default_date)); datestamp(git_default_date, sizeof(git_default_date));

View File

@ -243,9 +243,20 @@ static int eatspace(char *line)
#define SEEN_BOGUS_UNIX_FROM 010 #define SEEN_BOGUS_UNIX_FROM 010
#define SEEN_PREFIX 020 #define SEEN_PREFIX 020
/* First lines of body can have From:, Date:, and Subject: */ /* First lines of body can have From:, Date:, and Subject: or empty */
static void handle_inbody_header(int *seen, char *line) static void handle_inbody_header(int *seen, char *line)
{ {
if (*seen & SEEN_PREFIX)
return;
if (isspace(*line)) {
char *cp;
for (cp = line + 1; *cp; cp++) {
if (!isspace(*cp))
break;
}
if (!*cp)
return;
}
if (!memcmp(">From", line, 5) && isspace(line[5])) { if (!memcmp(">From", line, 5) && isspace(line[5])) {
if (!(*seen & SEEN_BOGUS_UNIX_FROM)) { if (!(*seen & SEEN_BOGUS_UNIX_FROM)) {
*seen |= SEEN_BOGUS_UNIX_FROM; *seen |= SEEN_BOGUS_UNIX_FROM;
@ -314,6 +325,7 @@ static char *cleanup_subject(char *subject)
} }
break; break;
} }
eatspace(subject);
return subject; return subject;
} }
} }
@ -420,9 +432,7 @@ static int read_one_header_line(char *line, int sz, FILE *in)
if (fgets(line + ofs, sz - ofs, in) == NULL) if (fgets(line + ofs, sz - ofs, in) == NULL)
break; break;
len = eatspace(line + ofs); len = eatspace(line + ofs);
if (len == 0) if ((len == 0) || !is_rfc2822_header(line)) {
break;
if (!is_rfc2822_header(line)) {
/* Re-add the newline */ /* Re-add the newline */
line[ofs + len] = '\n'; line[ofs + len] = '\n';
line[ofs + len + 1] = '\0'; line[ofs + len + 1] = '\0';
@ -762,10 +772,8 @@ static void handle_body(void)
{ {
int seen = 0; int seen = 0;
if (line[0] || fgets(line, sizeof(line), stdin) != NULL) { handle_commit_msg(&seen);
handle_commit_msg(&seen); handle_patch();
handle_patch();
}
fclose(patchfile); fclose(patchfile);
if (!patch_lines) { if (!patch_lines) {
fprintf(stderr, "No patch found\n"); fprintf(stderr, "No patch found\n");

View File

@ -46,7 +46,7 @@ void setup_pager(void)
close(fd[0]); close(fd[0]);
close(fd[1]); close(fd[1]);
setenv("LESS", "-S", 0); setenv("LESS", "-RS", 0);
run_pager(pager); run_pager(pager);
die("unable to execute pager '%s'", pager); die("unable to execute pager '%s'", pager);
exit(255); exit(255);

13
path.c
View File

@ -83,14 +83,19 @@ int git_mkstemp(char *path, size_t len, const char *template)
} }
char *safe_strncpy(char *dest, const char *src, size_t n) size_t safe_strncpy(char *dest, const char *src, size_t size)
{ {
strncpy(dest, src, n); size_t ret = strlen(src);
dest[n - 1] = '\0';
return dest; if (size) {
size_t len = (ret >= size) ? size - 1 : ret;
memcpy(dest, src, len);
dest[len] = '\0';
}
return ret;
} }
int validate_symref(const char *path) int validate_symref(const char *path)
{ {
struct stat st; struct stat st;

View File

@ -303,7 +303,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
parse_commit(p); parse_commit(p);
switch (rev_compare_tree(revs, p->tree, commit->tree)) { switch (rev_compare_tree(revs, p->tree, commit->tree)) {
case REV_TREE_SAME: case REV_TREE_SAME:
if (p->object.flags & UNINTERESTING) { if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {
/* Even if a merge with an uninteresting /* Even if a merge with an uninteresting
* side branch brought the entire change * side branch brought the entire change
* we are interested in, we do not want * we are interested in, we do not want
@ -519,6 +519,7 @@ void init_revisions(struct rev_info *revs)
revs->abbrev = DEFAULT_ABBREV; revs->abbrev = DEFAULT_ABBREV;
revs->ignore_merges = 1; revs->ignore_merges = 1;
revs->simplify_history = 1;
revs->pruning.recursive = 1; revs->pruning.recursive = 1;
revs->pruning.add_remove = file_add_remove; revs->pruning.add_remove = file_add_remove;
revs->pruning.change = file_change; revs->pruning.change = file_change;
@ -756,6 +757,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->full_diff = 1; revs->full_diff = 1;
continue; continue;
} }
if (!strcmp(arg, "--full-history")) {
revs->simplify_history = 0;
continue;
}
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i); opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
if (opts > 0) { if (opts > 0) {
revs->diff = 1; revs->diff = 1;

View File

@ -30,6 +30,7 @@ struct rev_info {
no_merges:1, no_merges:1,
no_walk:1, no_walk:1,
remove_empty_trees:1, remove_empty_trees:1,
simplify_history:1,
lifo:1, lifo:1,
topo_order:1, topo_order:1,
tag_objects:1, tag_objects:1,

View File

@ -262,8 +262,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
if (str[am] == '@' && str[am+1] == '{' && str[len-1] == '}') { if (str[am] == '@' && str[am+1] == '{' && str[len-1] == '}') {
int date_len = len - am - 3; int date_len = len - am - 3;
char *date_spec = xmalloc(date_len + 1); char *date_spec = xmalloc(date_len + 1);
strncpy(date_spec, str + am + 2, date_len); safe_strncpy(date_spec, str + am + 2, date_len + 1);
date_spec[date_len] = 0;
at_time = approxidate(date_spec); at_time = approxidate(date_spec);
free(date_spec); free(date_spec);
len = am; len = am;

View File

@ -20,14 +20,10 @@ do
for j in 0 1 2 3 for j in 0 1 2 3
do do
test $i -eq $j && continue test $i -eq $j && continue
diff -u frotz.$i frotz.$j |
sed -e '
/^---/s|.*|--- a/frotz|
/^+++/s|.*|+++ b/frotz|' >diff.$i-$j
cat frotz.$i >frotz cat frotz.$i >frotz
test_expect_success \ test_expect_success \
"apply diff between $i and $j" \ "apply diff between $i and $j" \
"git-apply <diff.$i-$j && diff frotz.$j frotz" "git-apply <../t4101/diff.$i-$j && diff frotz.$j frotz"
done done
done done

6
t/t4101/diff.0-1 Normal file
View File

@ -0,0 +1,6 @@
--- a/frotz
+++ b/frotz
@@ -1,2 +1,3 @@
a
b
+c

7
t/t4101/diff.0-2 Normal file
View File

@ -0,0 +1,7 @@
--- a/frotz
+++ b/frotz
@@ -1,2 +1,2 @@
a
-b
+b
\ No newline at end of file

8
t/t4101/diff.0-3 Normal file
View File

@ -0,0 +1,8 @@
--- a/frotz
+++ b/frotz
@@ -1,2 +1,3 @@
a
-b
+c
+b
\ No newline at end of file

6
t/t4101/diff.1-0 Normal file
View File

@ -0,0 +1,6 @@
--- a/frotz
+++ b/frotz
@@ -1,3 +1,2 @@
a
b
-c

8
t/t4101/diff.1-2 Normal file
View File

@ -0,0 +1,8 @@
--- a/frotz
+++ b/frotz
@@ -1,3 +1,2 @@
a
-b
-c
+b
\ No newline at end of file

8
t/t4101/diff.1-3 Normal file
View File

@ -0,0 +1,8 @@
--- a/frotz
+++ b/frotz
@@ -1,3 +1,3 @@
a
-b
c
+b
\ No newline at end of file

7
t/t4101/diff.2-0 Normal file
View File

@ -0,0 +1,7 @@
--- a/frotz
+++ b/frotz
@@ -1,2 +1,2 @@
a
-b
\ No newline at end of file
+b

8
t/t4101/diff.2-1 Normal file
View File

@ -0,0 +1,8 @@
--- a/frotz
+++ b/frotz
@@ -1,2 +1,3 @@
a
-b
\ No newline at end of file
+b
+c

7
t/t4101/diff.2-3 Normal file
View File

@ -0,0 +1,7 @@
--- a/frotz
+++ b/frotz
@@ -1,2 +1,3 @@
a
+c
b
\ No newline at end of file

8
t/t4101/diff.3-0 Normal file
View File

@ -0,0 +1,8 @@
--- a/frotz
+++ b/frotz
@@ -1,3 +1,2 @@
a
-c
-b
\ No newline at end of file
+b

8
t/t4101/diff.3-1 Normal file
View File

@ -0,0 +1,8 @@
--- a/frotz
+++ b/frotz
@@ -1,3 +1,3 @@
a
+b
c
-b
\ No newline at end of file

7
t/t4101/diff.3-2 Normal file
View File

@ -0,0 +1,7 @@
--- a/frotz
+++ b/frotz
@@ -1,3 +1,2 @@
a
-c
b
\ No newline at end of file

28
t/t5100-mailinfo.sh Executable file
View File

@ -0,0 +1,28 @@
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano
#
test_description='git-mailinfo and git-mailsplit test'
. ./test-lib.sh
test_expect_success 'split sample box' \
'git-mailsplit -o. ../t5100/sample.mbox >last &&
last=`cat last` &&
echo total is $last &&
test `cat last` = 5'
for mail in `echo 00*`
do
test_expect_success "mailinfo $mail" \
"git-mailinfo -u msg$mail patch$mail <$mail >info$mail &&
echo msg &&
diff ../t5100/msg$mail msg$mail &&
echo patch &&
diff ../t5100/patch$mail patch$mail &&
echo info &&
diff ../t5100/info$mail info$mail"
done
test_done

5
t/t5100/info0001 Normal file
View File

@ -0,0 +1,5 @@
Author: A U Thor
Email: a.u.thor@example.com
Subject: a commit.
Date: Fri, 9 Jun 2006 00:44:16 -0700

5
t/t5100/info0002 Normal file
View File

@ -0,0 +1,5 @@
Author: A U Thor
Email: a.u.thor@example.com
Subject: another patch
Date: Fri, 9 Jun 2006 00:44:16 -0700

5
t/t5100/info0003 Normal file
View File

@ -0,0 +1,5 @@
Author: A U Thor
Email: a.u.thor@example.com
Subject: third patch
Date: Fri, 9 Jun 2006 00:44:16 -0700

5
t/t5100/info0004 Normal file
View File

@ -0,0 +1,5 @@
Author: YOSHIFUJI Hideaki / 吉藤英明
Email: yoshfuji@linux-ipv6.org
Subject: GIT: Try all addresses for given remote name
Date: Thu, 21 Jul 2005 09:10:36 -0400 (EDT)

5
t/t5100/info0005 Normal file
View File

@ -0,0 +1,5 @@
Author: David Kågedal
Email: davidk@lysator.liu.se
Subject: Fixed two bugs in git-cvsimport-script.
Date: Mon, 15 Aug 2005 20:18:25 +0200

2
t/t5100/msg0001 Normal file
View File

@ -0,0 +1,2 @@
Here is a patch from A U Thor.

21
t/t5100/msg0002 Normal file
View File

@ -0,0 +1,21 @@
Here is a patch from A U Thor. This addresses the issue raised in the
message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
Message-Id: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.
I have included an extra blank line above, but it does not have to be
stripped away here, along with the
whitespaces at the end of the above line. They are expected to be squashed
when the message is made into a commit log by stripspace,
Also, there are three blank lines after this paragraph,
two truly blank and another full of spaces in between.
Hope this helps.

9
t/t5100/msg0003 Normal file
View File

@ -0,0 +1,9 @@
Here is a patch from A U Thor. This addresses the issue raised in the
message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
Message-Id: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.

7
t/t5100/msg0004 Normal file
View File

@ -0,0 +1,7 @@
Hello.
Try all addresses for given remote name until it succeeds.
Also supports IPv6.
Signed-of-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>

13
t/t5100/msg0005 Normal file
View File

@ -0,0 +1,13 @@
The git-cvsimport-script had a copule of small bugs that prevented me
from importing a big CVS repository.
The first was that it didn't handle removed files with a multi-digit
primary revision number.
The second was that it was asking the CVS server for "F" messages,
although they were not handled.
I also updated the documentation for that script to correspond to
actual flags.
Signed-off-by: David Kågedal <davidk@lysator.liu.se>

14
t/t5100/patch0001 Normal file
View File

@ -0,0 +1,14 @@
---
foo | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/foo b/foo
index 9123cdc..918dcf8 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-Fri Jun 9 00:44:04 PDT 2006
+Fri Jun 9 00:44:13 PDT 2006
--
1.4.0.g6f2b

14
t/t5100/patch0002 Normal file
View File

@ -0,0 +1,14 @@
---
foo | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/foo b/foo
index 9123cdc..918dcf8 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-Fri Jun 9 00:44:04 PDT 2006
+Fri Jun 9 00:44:13 PDT 2006
--
1.4.0.g6f2b

14
t/t5100/patch0003 Normal file
View File

@ -0,0 +1,14 @@
---
foo | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/foo b/foo
index 9123cdc..918dcf8 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-Fri Jun 9 00:44:04 PDT 2006
+Fri Jun 9 00:44:13 PDT 2006
--
1.4.0.g6f2b

93
t/t5100/patch0004 Normal file
View File

@ -0,0 +1,93 @@
diff --git a/connect.c b/connect.c
--- a/connect.c
+++ b/connect.c
@@ -96,42 +96,57 @@ static enum protocol get_protocol(const
die("I don't handle protocol '%s'", name);
}
-static void lookup_host(const char *host, struct sockaddr *in)
-{
- struct addrinfo *res;
- int ret;
-
- ret = getaddrinfo(host, NULL, NULL, &res);
- if (ret)
- die("Unable to look up %s (%s)", host, gai_strerror(ret));
- *in = *res->ai_addr;
- freeaddrinfo(res);
-}
+#define STR_(s) # s
+#define STR(s) STR_(s)
static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
{
- struct sockaddr addr;
- int port = DEFAULT_GIT_PORT, sockfd;
- char *colon;
-
- colon = strchr(host, ':');
- if (colon) {
- char *end;
- unsigned long n = strtoul(colon+1, &end, 0);
- if (colon[1] && !*end) {
- *colon = 0;
- port = n;
+ int sockfd = -1;
+ char *colon, *end;
+ char *port = STR(DEFAULT_GIT_PORT);
+ struct addrinfo hints, *ai0, *ai;
+ int gai;
+
+ if (host[0] == '[') {
+ end = strchr(host + 1, ']');
+ if (end) {
+ *end = 0;
+ end++;
+ host++;
+ } else
+ end = host;
+ } else
+ end = host;
+ colon = strchr(end, ':');
+
+ if (colon)
+ port = colon + 1;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ gai = getaddrinfo(host, port, &hints, &ai);
+ if (gai)
+ die("Unable to look up %s (%s)", host, gai_strerror(gai));
+
+ for (ai0 = ai; ai; ai = ai->ai_next) {
+ sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (sockfd < 0)
+ continue;
+ if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
+ close(sockfd);
+ sockfd = -1;
+ continue;
}
+ break;
}
- lookup_host(host, &addr);
- ((struct sockaddr_in *)&addr)->sin_port = htons(port);
+ freeaddrinfo(ai0);
- sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
if (sockfd < 0)
die("unable to create socket (%s)", strerror(errno));
- if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0)
- die("unable to connect (%s)", strerror(errno));
+
fd[0] = sockfd;
fd[1] = sockfd;
packet_write(sockfd, "%s %s\n", prog, path);
--
YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA

69
t/t5100/patch0005 Normal file
View File

@ -0,0 +1,69 @@
---
Documentation/git-cvsimport-script.txt | 9 ++++++++-
git-cvsimport-script | 4 ++--
2 files changed, 10 insertions(+), 3 deletions(-)
50452f9c0c2df1f04d83a26266ba704b13861632
diff --git a/Documentation/git-cvsimport-script.txt b/Documentation/git-cvsimport-script.txt
--- a/Documentation/git-cvsimport-script.txt
+++ b/Documentation/git-cvsimport-script.txt
@@ -29,6 +29,10 @@ OPTIONS
currently, only the :local:, :ext: and :pserver: access methods
are supported.
+-C <target-dir>::
+ The GIT repository to import to. If the directory doesn't
+ exist, it will be created. Default is the current directory.
+
-i::
Import-only: don't perform a checkout after importing. This option
ensures the working directory and cache remain untouched and will
@@ -44,7 +48,7 @@ OPTIONS
-p <options-for-cvsps>::
Additional options for cvsps.
- The options '-x' and '-A' are implicit and should not be used here.
+ The options '-u' and '-A' are implicit and should not be used here.
If you need to pass multiple options, separate them with a comma.
@@ -57,6 +61,9 @@ OPTIONS
-h::
Print a short usage message and exit.
+-z <fuzz>::
+ Pass the timestamp fuzz factor to cvsps.
+
OUTPUT
------
If '-v' is specified, the script reports what it is doing.
diff --git a/git-cvsimport-script b/git-cvsimport-script
--- a/git-cvsimport-script
+++ b/git-cvsimport-script
@@ -190,7 +190,7 @@ sub conn {
$self->{'socketo'}->write("Root $repo\n");
# Trial and error says that this probably is the minimum set
- $self->{'socketo'}->write("Valid-responses ok error Valid-requests Mode M Mbinary E F Checked-in Created Updated Merged Removed\n");
+ $self->{'socketo'}->write("Valid-responses ok error Valid-requests Mode M Mbinary E Checked-in Created Updated Merged Removed\n");
$self->{'socketo'}->write("valid-requests\n");
$self->{'socketo'}->flush();
@@ -691,7 +691,7 @@ while(<CVS>) {
unlink($tmpname);
my $mode = pmode($cvs->{'mode'});
push(@new,[$mode, $sha, $fn]); # may be resurrected!
- } elsif($state == 9 and /^\s+(\S+):\d(?:\.\d+)+->(\d(?:\.\d+)+)\(DEAD\)\s*$/) {
+ } elsif($state == 9 and /^\s+(\S+):\d+(?:\.\d+)+->(\d+(?:\.\d+)+)\(DEAD\)\s*$/) {
my $fn = $1;
$fn =~ s#^/+##;
push(@old,$fn);
--
David K<>gedal
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html

317
t/t5100/sample.mbox Normal file
View File

@ -0,0 +1,317 @@
From nobody Mon Sep 17 00:00:00 2001
From: A U Thor <a.u.thor@example.com>
Date: Fri, 9 Jun 2006 00:44:16 -0700
Subject: [PATCH] a commit.
Here is a patch from A U Thor.
---
foo | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/foo b/foo
index 9123cdc..918dcf8 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-Fri Jun 9 00:44:04 PDT 2006
+Fri Jun 9 00:44:13 PDT 2006
--
1.4.0.g6f2b
From nobody Mon Sep 17 00:00:00 2001
From: A U Thor <a.u.thor@example.com>
Date: Fri, 9 Jun 2006 00:44:16 -0700
Subject: [PATCH] another patch
Here is a patch from A U Thor. This addresses the issue raised in the
message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
Message-Id: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.
I have included an extra blank line above, but it does not have to be
stripped away here, along with the
whitespaces at the end of the above line. They are expected to be squashed
when the message is made into a commit log by stripspace,
Also, there are three blank lines after this paragraph,
two truly blank and another full of spaces in between.
Hope this helps.
---
foo | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/foo b/foo
index 9123cdc..918dcf8 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-Fri Jun 9 00:44:04 PDT 2006
+Fri Jun 9 00:44:13 PDT 2006
--
1.4.0.g6f2b
From nobody Mon Sep 17 00:00:00 2001
From: Junio C Hamano <junio@kernel.org>
Date: Fri, 9 Jun 2006 00:44:16 -0700
Subject: re: [PATCH] another patch
From: A U Thor <a.u.thor@example.com>
Subject: [PATCH] third patch
Here is a patch from A U Thor. This addresses the issue raised in the
message:
From: Nit Picker <nit.picker@example.net>
Subject: foo is too old
Message-Id: <nitpicker.12121212@example.net>
Hopefully this would fix the problem stated there.
---
foo | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/foo b/foo
index 9123cdc..918dcf8 100644
--- a/foo
+++ b/foo
@@ -1 +1 @@
-Fri Jun 9 00:44:04 PDT 2006
+Fri Jun 9 00:44:13 PDT 2006
--
1.4.0.g6f2b
From nobody Sat Aug 27 23:07:49 2005
Path: news.gmane.org!not-for-mail
Message-ID: <20050721.091036.01119516.yoshfuji@linux-ipv6.org>
From: YOSHIFUJI Hideaki / =?iso-2022-jp?B?GyRCNUhGIzFRTEAbKEI=?=
<yoshfuji@linux-ipv6.org>
Newsgroups: gmane.comp.version-control.git
Subject: [PATCH 1/2] GIT: Try all addresses for given remote name
Date: Thu, 21 Jul 2005 09:10:36 -0400 (EDT)
Lines: 99
Organization: USAGI/WIDE Project
Approved: news@gmane.org
NNTP-Posting-Host: main.gmane.org
Mime-Version: 1.0
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Trace: sea.gmane.org 1121951434 29350 80.91.229.2 (21 Jul 2005 13:10:34 GMT)
X-Complaints-To: usenet@sea.gmane.org
NNTP-Posting-Date: Thu, 21 Jul 2005 13:10:34 +0000 (UTC)
Hello.
Try all addresses for given remote name until it succeeds.
Also supports IPv6.
Signed-of-by: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
diff --git a/connect.c b/connect.c
--- a/connect.c
+++ b/connect.c
@@ -96,42 +96,57 @@ static enum protocol get_protocol(const
die("I don't handle protocol '%s'", name);
}
-static void lookup_host(const char *host, struct sockaddr *in)
-{
- struct addrinfo *res;
- int ret;
-
- ret = getaddrinfo(host, NULL, NULL, &res);
- if (ret)
- die("Unable to look up %s (%s)", host, gai_strerror(ret));
- *in = *res->ai_addr;
- freeaddrinfo(res);
-}
+#define STR_(s) # s
+#define STR(s) STR_(s)
static int git_tcp_connect(int fd[2], const char *prog, char *host, char *path)
{
- struct sockaddr addr;
- int port = DEFAULT_GIT_PORT, sockfd;
- char *colon;
-
- colon = strchr(host, ':');
- if (colon) {
- char *end;
- unsigned long n = strtoul(colon+1, &end, 0);
- if (colon[1] && !*end) {
- *colon = 0;
- port = n;
+ int sockfd = -1;
+ char *colon, *end;
+ char *port = STR(DEFAULT_GIT_PORT);
+ struct addrinfo hints, *ai0, *ai;
+ int gai;
+
+ if (host[0] == '[') {
+ end = strchr(host + 1, ']');
+ if (end) {
+ *end = 0;
+ end++;
+ host++;
+ } else
+ end = host;
+ } else
+ end = host;
+ colon = strchr(end, ':');
+
+ if (colon)
+ port = colon + 1;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ gai = getaddrinfo(host, port, &hints, &ai);
+ if (gai)
+ die("Unable to look up %s (%s)", host, gai_strerror(gai));
+
+ for (ai0 = ai; ai; ai = ai->ai_next) {
+ sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+ if (sockfd < 0)
+ continue;
+ if (connect(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
+ close(sockfd);
+ sockfd = -1;
+ continue;
}
+ break;
}
- lookup_host(host, &addr);
- ((struct sockaddr_in *)&addr)->sin_port = htons(port);
+ freeaddrinfo(ai0);
- sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
if (sockfd < 0)
die("unable to create socket (%s)", strerror(errno));
- if (connect(sockfd, (void *)&addr, sizeof(addr)) < 0)
- die("unable to connect (%s)", strerror(errno));
+
fd[0] = sockfd;
fd[1] = sockfd;
packet_write(sockfd, "%s %s\n", prog, path);
--
YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
From nobody Sat Aug 27 23:07:49 2005
Path: news.gmane.org!not-for-mail
Message-ID: <u5tacjjdpxq.fsf@lysator.liu.se>
From: =?iso-8859-1?Q?David_K=E5gedal?= <davidk@lysator.liu.se>
Newsgroups: gmane.comp.version-control.git
Subject: [PATCH] Fixed two bugs in git-cvsimport-script.
Date: Mon, 15 Aug 2005 20:18:25 +0200
Lines: 83
Approved: news@gmane.org
NNTP-Posting-Host: main.gmane.org
Mime-Version: 1.0
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: QUOTED-PRINTABLE
X-Trace: sea.gmane.org 1124130247 31839 80.91.229.2 (15 Aug 2005 18:24:07 GMT)
X-Complaints-To: usenet@sea.gmane.org
NNTP-Posting-Date: Mon, 15 Aug 2005 18:24:07 +0000 (UTC)
Cc: "Junio C. Hamano" <junkio@cox.net>
Original-X-From: git-owner@vger.kernel.org Mon Aug 15 20:24:05 2005
The git-cvsimport-script had a copule of small bugs that prevented me
from importing a big CVS repository.
The first was that it didn't handle removed files with a multi-digit
primary revision number.
The second was that it was asking the CVS server for "F" messages,
although they were not handled.
I also updated the documentation for that script to correspond to
actual flags.
Signed-off-by: David K=E5gedal <davidk@lysator.liu.se>
---
Documentation/git-cvsimport-script.txt | 9 ++++++++-
git-cvsimport-script | 4 ++--
2 files changed, 10 insertions(+), 3 deletions(-)
50452f9c0c2df1f04d83a26266ba704b13861632
diff --git a/Documentation/git-cvsimport-script.txt b/Documentation/git=
-cvsimport-script.txt
--- a/Documentation/git-cvsimport-script.txt
+++ b/Documentation/git-cvsimport-script.txt
@@ -29,6 +29,10 @@ OPTIONS
currently, only the :local:, :ext: and :pserver: access methods=20
are supported.
=20
+-C <target-dir>::
+ The GIT repository to import to. If the directory doesn't
+ exist, it will be created. Default is the current directory.
+
-i::
Import-only: don't perform a checkout after importing. This option
ensures the working directory and cache remain untouched and will
@@ -44,7 +48,7 @@ OPTIONS
=20
-p <options-for-cvsps>::
Additional options for cvsps.
- The options '-x' and '-A' are implicit and should not be used here.
+ The options '-u' and '-A' are implicit and should not be used here.
=20
If you need to pass multiple options, separate them with a comma.
=20
@@ -57,6 +61,9 @@ OPTIONS
-h::
Print a short usage message and exit.
=20
+-z <fuzz>::
+ Pass the timestamp fuzz factor to cvsps.
+
OUTPUT
------
If '-v' is specified, the script reports what it is doing.
diff --git a/git-cvsimport-script b/git-cvsimport-script
--- a/git-cvsimport-script
+++ b/git-cvsimport-script
@@ -190,7 +190,7 @@ sub conn {
$self->{'socketo'}->write("Root $repo\n");
=20
# Trial and error says that this probably is the minimum set
- $self->{'socketo'}->write("Valid-responses ok error Valid-requests Mo=
de M Mbinary E F Checked-in Created Updated Merged Removed\n");
+ $self->{'socketo'}->write("Valid-responses ok error Valid-requests Mo=
de M Mbinary E Checked-in Created Updated Merged Removed\n");
=20
$self->{'socketo'}->write("valid-requests\n");
$self->{'socketo'}->flush();
@@ -691,7 +691,7 @@ while(<CVS>) {
unlink($tmpname);
my $mode =3D pmode($cvs->{'mode'});
push(@new,[$mode, $sha, $fn]); # may be resurrected!
- } elsif($state =3D=3D 9 and /^\s+(\S+):\d(?:\.\d+)+->(\d(?:\.\d+)+)\(=
DEAD\)\s*$/) {
+ } elsif($state =3D=3D 9 and /^\s+(\S+):\d+(?:\.\d+)+->(\d+(?:\.\d+)+)=
\(DEAD\)\s*$/) {
my $fn =3D $1;
$fn =3D~ s#^/+##;
push(@old,$fn);
--=20
David K=E5gedal
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html