diff --git a/archive-zip.c b/archive-zip.c index 3ffdad68d1..28e7352e98 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -145,6 +145,7 @@ static int write_zip_entry(const unsigned char *sha1, { struct zip_local_header header; struct zip_dir_header dirent; + unsigned long attr2; unsigned long compressed_size; unsigned long uncompressed_size; unsigned long crc; @@ -172,12 +173,16 @@ static int write_zip_entry(const unsigned char *sha1, if (S_ISDIR(mode)) { method = 0; + attr2 = 16; result = READ_TREE_RECURSIVE; out = NULL; uncompressed_size = 0; compressed_size = 0; - } else if (S_ISREG(mode)) { - method = zlib_compression_level == 0 ? 0 : 8; + } else if (S_ISREG(mode) || S_ISLNK(mode)) { + method = 0; + attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : 0; + if (S_ISREG(mode) && zlib_compression_level != 0) + method = 8; result = 0; buffer = read_sha1_file(sha1, type, &size); if (!buffer) @@ -213,8 +218,8 @@ static int write_zip_entry(const unsigned char *sha1, } copy_le32(dirent.magic, 0x02014b50); - copy_le16(dirent.creator_version, 0); - copy_le16(dirent.version, 20); + copy_le16(dirent.creator_version, S_ISLNK(mode) ? 0x0317 : 0); + copy_le16(dirent.version, 10); copy_le16(dirent.flags, 0); copy_le16(dirent.compression_method, method); copy_le16(dirent.mtime, zip_time); @@ -227,7 +232,7 @@ static int write_zip_entry(const unsigned char *sha1, copy_le16(dirent.comment_length, 0); copy_le16(dirent.disk, 0); copy_le16(dirent.attr1, 0); - copy_le32(dirent.attr2, 0); + copy_le32(dirent.attr2, attr2); copy_le32(dirent.offset, zip_offset); memcpy(zip_dir + zip_dir_offset, &dirent, sizeof(struct zip_dir_header)); zip_dir_offset += sizeof(struct zip_dir_header); @@ -236,7 +241,7 @@ static int write_zip_entry(const unsigned char *sha1, zip_dir_entries++; copy_le32(header.magic, 0x04034b50); - copy_le16(header.version, 20); + copy_le16(header.version, 10); copy_le16(header.flags, 0); copy_le16(header.compression_method, method); copy_le16(header.mtime, zip_time); diff --git a/git-commit.sh b/git-commit.sh index 64265c7f50..4bd0e46c42 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -41,21 +41,21 @@ run_status () { # so the regular index file is what we use to compare. if test '' != "$TMP_INDEX" then - GIT_INDEX_FILE="$TMP_INDEX" - export GIT_INDEX_FILE + GIT_INDEX_FILE="$TMP_INDEX" + export GIT_INDEX_FILE elif test -f "$NEXT_INDEX" then - GIT_INDEX_FILE="$NEXT_INDEX" - export GIT_INDEX_FILE + GIT_INDEX_FILE="$NEXT_INDEX" + export GIT_INDEX_FILE fi - case "$status_only" in - t) color= ;; - *) color=--nocolor ;; - esac - git-runstatus ${color} \ - ${verbose:+--verbose} \ - ${amend:+--amend} \ + case "$status_only" in + t) color= ;; + *) color=--nocolor ;; + esac + git-runstatus ${color} \ + ${verbose:+--verbose} \ + ${amend:+--amend} \ ${untracked_files:+--untracked} } @@ -87,179 +87,181 @@ only_include_assumed= untracked_files= while case "$#" in 0) break;; esac do - case "$1" in - -F|--F|-f|--f|--fi|--fil|--file) - case "$#" in 1) usage ;; esac - shift - no_edit=t - log_given=t$log_given - logfile="$1" - shift - ;; - -F*|-f*) - no_edit=t - log_given=t$log_given - logfile=`expr "z$1" : 'z-[Ff]\(.*\)'` - shift - ;; - --F=*|--f=*|--fi=*|--fil=*|--file=*) - no_edit=t - log_given=t$log_given - logfile=`expr "z$1" : 'z-[^=]*=\(.*\)'` - shift - ;; - -a|--a|--al|--all) - all=t - shift - ;; - --au=*|--aut=*|--auth=*|--autho=*|--author=*) - force_author=`expr "z$1" : 'z-[^=]*=\(.*\)'` - shift - ;; - --au|--aut|--auth|--autho|--author) - case "$#" in 1) usage ;; esac - shift - force_author="$1" - shift - ;; - -e|--e|--ed|--edi|--edit) - edit_flag=t - shift - ;; - -i|--i|--in|--inc|--incl|--inclu|--includ|--include) - also=t - shift - ;; - -o|--o|--on|--onl|--only) - only=t - shift - ;; - -m|--m|--me|--mes|--mess|--messa|--messag|--message) - case "$#" in 1) usage ;; esac - shift - log_given=m$log_given - if test "$log_message" = '' - then - log_message="$1" - else - log_message="$log_message + case "$1" in + -F|--F|-f|--f|--fi|--fil|--file) + case "$#" in 1) usage ;; esac + shift + no_edit=t + log_given=t$log_given + logfile="$1" + shift + ;; + -F*|-f*) + no_edit=t + log_given=t$log_given + logfile=`expr "z$1" : 'z-[Ff]\(.*\)'` + shift + ;; + --F=*|--f=*|--fi=*|--fil=*|--file=*) + no_edit=t + log_given=t$log_given + logfile=`expr "z$1" : 'z-[^=]*=\(.*\)'` + shift + ;; + -a|--a|--al|--all) + all=t + shift + ;; + --au=*|--aut=*|--auth=*|--autho=*|--author=*) + force_author=`expr "z$1" : 'z-[^=]*=\(.*\)'` + shift + ;; + --au|--aut|--auth|--autho|--author) + case "$#" in 1) usage ;; esac + shift + force_author="$1" + shift + ;; + -e|--e|--ed|--edi|--edit) + edit_flag=t + shift + ;; + -i|--i|--in|--inc|--incl|--inclu|--includ|--include) + also=t + shift + ;; + -o|--o|--on|--onl|--only) + only=t + shift + ;; + -m|--m|--me|--mes|--mess|--messa|--messag|--message) + case "$#" in 1) usage ;; esac + shift + log_given=m$log_given + if test "$log_message" = '' + then + log_message="$1" + else + log_message="$log_message $1" - fi - no_edit=t - shift - ;; - -m*) - log_given=m$log_given - if test "$log_message" = '' - then - log_message=`expr "z$1" : 'z-m\(.*\)'` - else - log_message="$log_message + fi + no_edit=t + shift + ;; + -m*) + log_given=m$log_given + if test "$log_message" = '' + then + log_message=`expr "z$1" : 'z-m\(.*\)'` + else + log_message="$log_message `expr "z$1" : 'z-m\(.*\)'`" - fi - no_edit=t - shift - ;; - --m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*) - log_given=m$log_given - if test "$log_message" = '' - then - log_message=`expr "z$1" : 'z-[^=]*=\(.*\)'` - else - log_message="$log_message + fi + no_edit=t + shift + ;; + --m=*|--me=*|--mes=*|--mess=*|--messa=*|--messag=*|--message=*) + log_given=m$log_given + if test "$log_message" = '' + then + log_message=`expr "z$1" : 'z-[^=]*=\(.*\)'` + else + log_message="$log_message `expr "z$1" : 'zq-[^=]*=\(.*\)'`" - fi - no_edit=t - shift - ;; - -n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|--no-verify) - verify= - shift - ;; - --a|--am|--ame|--amen|--amend) - amend=t - log_given=t$log_given - use_commit=HEAD - shift - ;; - -c) - case "$#" in 1) usage ;; esac - shift - log_given=t$log_given - use_commit="$1" - no_edit= - shift - ;; - --ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\ - --reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\ - --reedit-messag=*|--reedit-message=*) - log_given=t$log_given - use_commit=`expr "z$1" : 'z-[^=]*=\(.*\)'` - no_edit= - shift - ;; - --ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\ - --reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|--reedit-message) - case "$#" in 1) usage ;; esac - shift - log_given=t$log_given - use_commit="$1" - no_edit= - shift - ;; - -C) - case "$#" in 1) usage ;; esac - shift - log_given=t$log_given - use_commit="$1" - no_edit=t - shift - ;; - --reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\ - --reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\ - --reuse-message=*) - log_given=t$log_given - use_commit=`expr "z$1" : 'z-[^=]*=\(.*\)'` - no_edit=t - shift - ;; - --reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\ - --reuse-mess|--reuse-messa|--reuse-messag|--reuse-message) - case "$#" in 1) usage ;; esac - shift - log_given=t$log_given - use_commit="$1" - no_edit=t - shift - ;; - -s|--s|--si|--sig|--sign|--signo|--signof|--signoff) - signoff=t - shift - ;; - -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) - verbose=t - shift - ;; - -u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|--untracked|\ - --untracked-|--untracked-f|--untracked-fi|--untracked-fil|--untracked-file|\ - --untracked-files) - untracked_files=t - shift - ;; - --) - shift - break - ;; - -*) - usage - ;; - *) - break - ;; - esac + fi + no_edit=t + shift + ;; + -n|--n|--no|--no-|--no-v|--no-ve|--no-ver|--no-veri|--no-verif|\ + --no-verify) + verify= + shift + ;; + --a|--am|--ame|--amen|--amend) + amend=t + log_given=t$log_given + use_commit=HEAD + shift + ;; + -c) + case "$#" in 1) usage ;; esac + shift + log_given=t$log_given + use_commit="$1" + no_edit= + shift + ;; + --ree=*|--reed=*|--reedi=*|--reedit=*|--reedit-=*|--reedit-m=*|\ + --reedit-me=*|--reedit-mes=*|--reedit-mess=*|--reedit-messa=*|\ + --reedit-messag=*|--reedit-message=*) + log_given=t$log_given + use_commit=`expr "z$1" : 'z-[^=]*=\(.*\)'` + no_edit= + shift + ;; + --ree|--reed|--reedi|--reedit|--reedit-|--reedit-m|--reedit-me|\ + --reedit-mes|--reedit-mess|--reedit-messa|--reedit-messag|\ + --reedit-message) + case "$#" in 1) usage ;; esac + shift + log_given=t$log_given + use_commit="$1" + no_edit= + shift + ;; + -C) + case "$#" in 1) usage ;; esac + shift + log_given=t$log_given + use_commit="$1" + no_edit=t + shift + ;; + --reu=*|--reus=*|--reuse=*|--reuse-=*|--reuse-m=*|--reuse-me=*|\ + --reuse-mes=*|--reuse-mess=*|--reuse-messa=*|--reuse-messag=*|\ + --reuse-message=*) + log_given=t$log_given + use_commit=`expr "z$1" : 'z-[^=]*=\(.*\)'` + no_edit=t + shift + ;; + --reu|--reus|--reuse|--reuse-|--reuse-m|--reuse-me|--reuse-mes|\ + --reuse-mess|--reuse-messa|--reuse-messag|--reuse-message) + case "$#" in 1) usage ;; esac + shift + log_given=t$log_given + use_commit="$1" + no_edit=t + shift + ;; + -s|--s|--si|--sig|--sign|--signo|--signof|--signoff) + signoff=t + shift + ;; + -v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose) + verbose=t + shift + ;; + -u|--u|--un|--unt|--untr|--untra|--untrac|--untrack|--untracke|\ + --untracked|--untracked-|--untracked-f|--untracked-fi|--untracked-fil|\ + --untracked-file|--untracked-files) + untracked_files=t + shift + ;; + --) + shift + break + ;; + -*) + usage + ;; + *) + break + ;; + esac done case "$edit_flag" in t) no_edit= ;; esac @@ -268,33 +270,33 @@ case "$edit_flag" in t) no_edit= ;; esac case "$amend,$initial_commit" in t,t) - die "You do not have anything to amend." ;; + die "You do not have anything to amend." ;; t,) - if [ -f "$GIT_DIR/MERGE_HEAD" ]; then - die "You are in the middle of a merge -- cannot amend." - fi ;; + if [ -f "$GIT_DIR/MERGE_HEAD" ]; then + die "You are in the middle of a merge -- cannot amend." + fi ;; esac case "$log_given" in tt*) - die "Only one of -c/-C/-F can be used." ;; + die "Only one of -c/-C/-F can be used." ;; *tm*|*mt*) - die "Option -m cannot be combined with -c/-C/-F." ;; + die "Option -m cannot be combined with -c/-C/-F." ;; esac case "$#,$also,$only,$amend" in *,t,t,*) - die "Only one of --include/--only can be used." ;; + die "Only one of --include/--only can be used." ;; 0,t,,* | 0,,t,) - die "No paths with --include/--only does not make sense." ;; + die "No paths with --include/--only does not make sense." ;; 0,,t,t) - only_include_assumed="# Clever... amending the last one with dirty index." ;; + only_include_assumed="# Clever... amending the last one with dirty index." ;; 0,,,*) - ;; + ;; *,,,*) - only_include_assumed="# Explicit paths specified without -i nor -o; assuming --only paths..." - also= - ;; + only_include_assumed="# Explicit paths specified without -i nor -o; assuming --only paths..." + also= + ;; esac unset only case "$all,$also,$#" in @@ -341,47 +343,47 @@ t,) ,) case "$#" in 0) - ;; # commit as-is + ;; # commit as-is *) - if test -f "$GIT_DIR/MERGE_HEAD" - then - refuse_partial "Cannot do a partial commit during a merge." - fi - TMP_INDEX="$GIT_DIR/tmp-index$$" - if test -z "$initial_commit" - then - # make sure index is clean at the specified paths, or - # they are additions. - dirty_in_index=`git-diff-index --cached --name-status \ - --diff-filter=DMTU HEAD -- "$@"` - test -z "$dirty_in_index" || - refuse_partial "Different in index and the last commit: + if test -f "$GIT_DIR/MERGE_HEAD" + then + refuse_partial "Cannot do a partial commit during a merge." + fi + TMP_INDEX="$GIT_DIR/tmp-index$$" + if test -z "$initial_commit" + then + # make sure index is clean at the specified paths, or + # they are additions. + dirty_in_index=`git-diff-index --cached --name-status \ + --diff-filter=DMTU HEAD -- "$@"` + test -z "$dirty_in_index" || + refuse_partial "Different in index and the last commit: $dirty_in_index" - fi - commit_only=`git-ls-files --error-unmatch -- "$@"` || exit + fi + commit_only=`git-ls-files --error-unmatch -- "$@"` || exit - # Build the temporary index and update the real index - # the same way. - if test -z "$initial_commit" - then - cp "$THIS_INDEX" "$TMP_INDEX" - GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -m HEAD - else - rm -f "$TMP_INDEX" - fi || exit + # Build the temporary index and update the real index + # the same way. + if test -z "$initial_commit" + then + cp "$THIS_INDEX" "$TMP_INDEX" + GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -m HEAD + else + rm -f "$TMP_INDEX" + fi || exit - echo "$commit_only" | - GIT_INDEX_FILE="$TMP_INDEX" \ - git-update-index --add --remove --stdin && + echo "$commit_only" | + GIT_INDEX_FILE="$TMP_INDEX" \ + git-update-index --add --remove --stdin && - save_index && - echo "$commit_only" | - ( - GIT_INDEX_FILE="$NEXT_INDEX" - export GIT_INDEX_FILE - git-update-index --remove --stdin - ) || exit - ;; + save_index && + echo "$commit_only" | + ( + GIT_INDEX_FILE="$NEXT_INDEX" + export GIT_INDEX_FILE + git-update-index --remove --stdin + ) || exit + ;; esac ;; esac @@ -399,7 +401,7 @@ else fi GIT_INDEX_FILE="$USE_INDEX" \ - git-update-index -q $unmerged_ok_if_status --refresh || exit + git-update-index -q $unmerged_ok_if_status --refresh || exit ################################################################ # If the request is status, just show it and exit. diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index b2e4f43716..ae68f08cd8 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1140,6 +1140,9 @@ sub parse_commit { last; } } + if ($co{'title'} eq "") { + $co{'title'} = $co{'title_short'} = '(no commit message)'; + } # remove added spaces foreach my $line (@commit_lines) { $line =~ s/^ //; @@ -2014,14 +2017,14 @@ sub git_patchset_body { print "
" . file_type($diffinfo->{'to_mode'}) . ":" . $cgi->a({-href => href(action=>"blob", hash_base=>$hash, hash=>$diffinfo->{'to_id'}, file_name=>$diffinfo->{'file'})}, - $diffinfo->{'to_id'}) . "(new)" . + $diffinfo->{'to_id'}) . " (new)" . "
\n"; # class="diff_info" } elsif ($diffinfo->{'status'} eq "D") { # deleted print "
" . file_type($diffinfo->{'from_mode'}) . ":" . $cgi->a({-href => href(action=>"blob", hash_base=>$hash_parent, hash=>$diffinfo->{'from_id'}, file_name=>$diffinfo->{'file'})}, - $diffinfo->{'from_id'}) . "(deleted)" . + $diffinfo->{'from_id'}) . " (deleted)" . "
\n"; # class="diff_info" } elsif ($diffinfo->{'status'} eq "R" || # renamed @@ -2125,8 +2128,10 @@ sub git_shortlog_body { print "\n" . "" . $cgi->a({-href => href(action=>"commitdiff", hash=>$commit)}, "commitdiff") . " | " . - $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree") . " | " . - $cgi->a({-href => href(action=>"snapshot", hash=>$commit)}, "snapshot"); + $cgi->a({-href => href(action=>"tree", hash=>$commit, hash_base=>$commit)}, "tree"); + if (gitweb_have_snapshot()) { + print " | " . $cgi->a({-href => href(action=>"snapshot", hash=>$commit)}, "snapshot"); + } print "\n" . "\n"; } @@ -3052,7 +3057,7 @@ sub git_commit { "blame"); } git_header_html(undef, $expires); - git_print_page_nav('commit', defined $co{'parent'} ? '' : 'commitdiff', + git_print_page_nav('commit', '', $hash, $co{'tree'}, $hash, join (' | ', @views_nav)); diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh index 278eb66701..cf08e9279c 100755 --- a/t/t5000-tar-tree.sh +++ b/t/t5000-tar-tree.sh @@ -26,6 +26,7 @@ commit id embedding: . ./test-lib.sh TAR=${TAR:-tar} +UNZIP=${UNZIP:-unzip} test_expect_success \ 'populate workdir' \ @@ -95,4 +96,38 @@ test_expect_success \ 'validate file contents with prefix' \ 'diff -r a c/prefix/a' +test_expect_success \ + 'git-archive --format=zip' \ + 'git-archive --format=zip HEAD >d.zip' + +test_expect_success \ + 'extract ZIP archive' \ + '(mkdir d && cd d && $UNZIP ../d.zip)' + +test_expect_success \ + 'validate filenames' \ + '(cd d/a && find .) | sort >d.lst && + diff a.lst d.lst' + +test_expect_success \ + 'validate file contents' \ + 'diff -r a d/a' + +test_expect_success \ + 'git-archive --format=zip with prefix' \ + 'git-archive --format=zip --prefix=prefix/ HEAD >e.zip' + +test_expect_success \ + 'extract ZIP archive with prefix' \ + '(mkdir e && cd e && $UNZIP ../e.zip)' + +test_expect_success \ + 'validate filenames with prefix' \ + '(cd e/prefix/a && find .) | sort >e.lst && + diff a.lst e.lst' + +test_expect_success \ + 'validate file contents with prefix' \ + 'diff -r a e/prefix/a' + test_done diff --git a/t/test-lib.sh b/t/test-lib.sh index b523fef339..2488e6eae1 100755 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -135,6 +135,7 @@ test_expect_failure () { else test_failure_ "$@" fi + echo >&3 "" } test_expect_success () { @@ -148,6 +149,7 @@ test_expect_success () { else test_failure_ "$@" fi + echo >&3 "" } test_expect_code () { @@ -161,6 +163,7 @@ test_expect_code () { else test_failure_ "$@" fi + echo >&3 "" } # Most tests can use the created repository, but some amy need to create more.