diff options
-rw-r--r-- | Documentation/git-diff-files.txt | 9 | ||||
-rw-r--r-- | Documentation/git-svnimport.txt | 13 | ||||
-rw-r--r-- | Documentation/pull-fetch-param.txt | 14 | ||||
-rw-r--r-- | Documentation/tutorial.txt | 15 | ||||
-rw-r--r-- | diff-files.c | 43 | ||||
-rwxr-xr-x | git-applymbox.sh | 2 | ||||
-rwxr-xr-x | git-applypatch.sh | 37 | ||||
-rwxr-xr-x | git-bisect.sh | 29 | ||||
-rwxr-xr-x | git-clone.sh | 2 | ||||
-rwxr-xr-x | git-diff.sh | 17 | ||||
-rwxr-xr-x | git-format-patch.sh | 9 | ||||
-rwxr-xr-x | git-merge-one-file.sh | 6 | ||||
-rwxr-xr-x | git-merge-recursive.py | 2 | ||||
-rwxr-xr-x | git-mv.perl | 12 | ||||
-rwxr-xr-x | git-svnimport.perl | 37 | ||||
-rwxr-xr-x | gitk | 142 | ||||
-rw-r--r-- | http-push.c | 5 | ||||
-rw-r--r-- | ls-tree.c | 249 | ||||
-rw-r--r-- | rev-list.c | 18 | ||||
-rw-r--r-- | setup.c | 2 | ||||
-rwxr-xr-x | t/t0000-basic.sh | 5 | ||||
-rwxr-xr-x | t/t3100-ls-tree-restrict.sh | 35 | ||||
-rw-r--r-- | t/t3101-ls-tree-dirname.sh | 38 | ||||
-rwxr-xr-x | t/t7001-mv.sh | 27 | ||||
-rw-r--r-- | tree.c | 34 | ||||
-rw-r--r-- | tree.h | 9 |
26 files changed, 379 insertions, 432 deletions
diff --git a/Documentation/git-diff-files.txt b/Documentation/git-diff-files.txt index 3b04bfeec6..67f51265e6 100644 --- a/Documentation/git-diff-files.txt +++ b/Documentation/git-diff-files.txt @@ -21,6 +21,15 @@ OPTIONS ------- include::diff-options.txt[] +-1 -2 -3 or --base --ours --theirs, and -0:: + Diff against the "base" version, "our branch" or "their + branch" respectively. With these options, diffs for + merged entries are not shown. ++ +The default is to diff against our branch (-2) and the +cleanly resolved paths. The option -0 can be given to +omit diff output for unmerged entries and just show "Unmerged". + -q:: Remain silent even on nonexisting files diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index fcc79fa93a..f8dbee7096 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -10,7 +10,7 @@ git-svnimport - Import a SVN repository into git SYNOPSIS -------- 'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ] - [ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_nr_changes] + [ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev] [ -b branch_subdir ] [ -t trunk_subdir ] [ -T tag_subdir ] [ -s start_chg ] [ -m ] [ -M regex ] <SVN_repository_URL> [ <path> ] @@ -71,14 +71,11 @@ When importing incementally, you might need to edit the .git/svn2git file. regex. It can be used with -m to also see the default regexes. You must escape forward slashes. --l <max_num_changes>:: - Limit the number of SVN changesets we pull before quitting. - This option is necessary because the SVN library has serious memory - leaks; the recommended value for nontrivial imports is 100. +-l <max_rev>:: + Specify a maximum revision number to pull. - git-svnimport will still exit with a zero exit code. You can check - the size of the file ".git/svn2git" to determine whether to call - the importer again. + Formerly, this option controlled how many revisions to pull, due to + SVN memory leaks. (These have been worked around.) -v:: Verbosity: let 'svnimport' report what it is doing. diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt index 6413d525ce..b5b979242c 100644 --- a/Documentation/pull-fetch-param.txt +++ b/Documentation/pull-fetch-param.txt @@ -15,10 +15,10 @@ - ssh://host.xz/~/path/to/repo.git =============================================================== + - SSH Is the default transport protocol and also supports an - scp-like syntax. Both syntaxes support username expansion, - as does the native git protocol. The following three are - identical to the last three above, respectively: +SSH Is the default transport protocol and also supports an +scp-like syntax. Both syntaxes support username expansion, +as does the native git protocol. The following three are +identical to the last three above, respectively: + =============================================================== - host.xz:/path/to/repo.git/ @@ -26,8 +26,8 @@ - host.xz:path/to/repo.git =============================================================== + - To sync with a local directory, use: - +To sync with a local directory, use: ++ =============================================================== - /path/to/repo.git/ =============================================================== @@ -113,7 +113,7 @@ on the remote branch, merge it into your development branch with `git pull . remote-B`, while you are on `my-B` branch. The common `Pull: master:origin` mapping of a remote `master` branch to a local `origin` branch, which is then merged to a -ocal development branch, again typically named `master`, is made +local development branch, again typically named `master`, is made when you run `git clone` for you to follow this pattern. + [NOTE] diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index e2dfb00ab1..cf7ba76ddf 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -898,9 +898,8 @@ file, which had no differences in the `mybranch` branch), and say: fatal: Merge requires file-level merging Nope. ... - merge: warning: conflicts during merge - ERROR: Merge conflict in hello. - fatal: merge program failed + Auto-merging hello + CONFLICT (content): Merge conflict in hello Automatic merge failed/prevented; fix up by hand ---------------- @@ -942,10 +941,10 @@ environment, is `git show-branch`. ------------------------------------------------ $ git show-branch master mybranch -* [master] Merged "mybranch" changes. +* [master] Merge work in mybranch ! [mybranch] Some work. -- -+ [master] Merged "mybranch" changes. ++ [master] Merge work in mybranch ++ [mybranch] Some work. ------------------------------------------------ @@ -998,10 +997,10 @@ looks like, or run `show-branch`, which tells you this. ------------------------------------------------ $ git show-branch master mybranch -! [master] Merged "mybranch" changes. - * [mybranch] Merged "mybranch" changes. +! [master] Merge work in mybranch + * [mybranch] Merge work in mybranch -- -++ [master] Merged "mybranch" changes. +++ [master] Merge work in mybranch ------------------------------------------------ diff --git a/diff-files.c b/diff-files.c index 38599b5b75..6c0696c34f 100644 --- a/diff-files.c +++ b/diff-files.c @@ -7,12 +7,12 @@ #include "diff.h" static const char diff_files_usage[] = -"git-diff-files [-q] " -"[<common diff options>] [<path>...]" +"git-diff-files [-q] [-0/-1/2/3] [<common diff options>] [<path>...]" COMMON_DIFF_OPTIONS_HELP; static struct diff_options diff_options; static int silent = 0; +static int diff_unmerged_stage = 2; static void show_unmerge(const char *path) { @@ -46,7 +46,21 @@ int main(int argc, const char **argv) argc--; break; } - if (!strcmp(argv[1], "-q")) + if (!strcmp(argv[1], "-0")) + diff_unmerged_stage = 0; + else if (!strcmp(argv[1], "-1")) + diff_unmerged_stage = 1; + else if (!strcmp(argv[1], "-2")) + diff_unmerged_stage = 2; + else if (!strcmp(argv[1], "-3")) + diff_unmerged_stage = 3; + else if (!strcmp(argv[1], "--base")) + diff_unmerged_stage = 1; + else if (!strcmp(argv[1], "--ours")) + diff_unmerged_stage = 2; + else if (!strcmp(argv[1], "--theirs")) + diff_unmerged_stage = 3; + else if (!strcmp(argv[1], "-q")) silent = 1; else if (!strcmp(argv[1], "-r")) ; /* no-op */ @@ -95,11 +109,26 @@ int main(int argc, const char **argv) if (ce_stage(ce)) { show_unmerge(ce->name); - while (i < entries && - !strcmp(ce->name, active_cache[i]->name)) + while (i < entries) { + struct cache_entry *nce = active_cache[i]; + + if (strcmp(ce->name, nce->name)) + break; + /* diff against the proper unmerged stage */ + if (ce_stage(nce) == diff_unmerged_stage) + ce = nce; i++; - i--; /* compensate for loop control increments */ - continue; + } + /* + * Compensate for loop update + */ + i--; + /* + * Show the diff for the 'ce' if we found the one + * from the desired stage. + */ + if (ce_stage(ce) != diff_unmerged_stage) + continue; } if (lstat(ce->name, &st) < 0) { diff --git a/git-applymbox.sh b/git-applymbox.sh index 24d4a8cb4e..c686cc8d27 100755 --- a/git-applymbox.sh +++ b/git-applymbox.sh @@ -33,7 +33,7 @@ do -k) keep_subject=-k ;; -q) query_apply=t ;; -c) continue="$2"; resume=f; shift ;; - -m) fallback_3way=t ;; + -m) fall_back_3way=t ;; -*) usage ;; *) break ;; esac diff --git a/git-applypatch.sh b/git-applypatch.sh index f0549960fb..4c577eb835 100755 --- a/git-applypatch.sh +++ b/git-applypatch.sh @@ -120,26 +120,36 @@ git-apply --index "$PATCHFILE" || { O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd` rm -fr .patch-merge-* + if git-apply -z --index-info "$PATCHFILE" \ + >.patch-merge-index-info 2>/dev/null && + GIT_INDEX_FILE=.patch-merge-tmp-index \ + git-update-index -z --index-info <.patch-merge-index-info && + GIT_INDEX_FILE=.patch-merge-tmp-index \ + git-write-tree >.patch-merge-tmp-base && + ( + mkdir .patch-merge-tmp-dir && + cd .patch-merge-tmp-dir && + GIT_INDEX_FILE="../.patch-merge-tmp-index" \ + GIT_OBJECT_DIRECTORY="$O_OBJECT" \ + git-apply $binary --index + ) <"$PATCHFILE" + then + echo Using index info to reconstruct a base tree... + mv .patch-merge-tmp-base .patch-merge-base + mv .patch-merge-tmp-index .patch-merge-index + else ( N=10 - # if the patch records the base tree... - sed -ne ' - /^diff /q - /^applies-to: \([0-9a-f]*\)$/{ - s//\1/p - q - } - ' "$PATCHFILE" - - # or hoping the patch is against our recent commits... + # Otherwise, try nearby trees that can be used to apply the + # patch. git-rev-list --max-count=$N HEAD # or hoping the patch is against known tags... git-ls-remote --tags . ) | - while read base junk - do + while read base junk + do # Try it if we have it as a tree. git-cat-file tree "$base" >/dev/null 2>&1 || continue @@ -155,7 +165,8 @@ git-apply --index "$PATCHFILE" || { mv ../.patch-merge-tmp-index ../.patch-merge-index && echo "$base" >../.patch-merge-base ) <"$PATCHFILE" 2>/dev/null && break - done + done + fi test -f .patch-merge-index && his_tree=$(GIT_INDEX_FILE=.patch-merge-index git-write-tree) && diff --git a/git-bisect.sh b/git-bisect.sh index d92993b94e..68838f3fad 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -1,9 +1,19 @@ #!/bin/sh . git-sh-setup +sq() { + perl -e ' + for (@ARGV) { + s/'\''/'\'\\\\\'\''/g; + print " '\''$_'\''"; + } + print "\n"; + ' "$@" +} + usage() { echo >&2 'usage: git bisect [start|bad|good|next|reset|visualize] -git bisect start reset bisect state and start bisection. +git bisect start [<pathspec>] reset bisect state and start bisection. git bisect bad [<rev>] mark <rev> a known-bad revision. git bisect good [<rev>...] mark <rev>... known-good revisions. git bisect next find next bisection to test and check it out. @@ -33,7 +43,6 @@ bisect_autostart() { } bisect_start() { - case "$#" in 0) ;; *) usage ;; esac # # Verify HEAD. If we were bisecting before this, reset to the # top-of-line master first! @@ -57,7 +66,11 @@ bisect_start() { rm -f "$GIT_DIR/refs/heads/bisect" rm -rf "$GIT_DIR/refs/bisect/" mkdir "$GIT_DIR/refs/bisect" - echo "git-bisect start" >"$GIT_DIR/BISECT_LOG" + { + echo -n "git-bisect start" + sq "$@" + } >"$GIT_DIR/BISECT_LOG" + sq "$@" >"$GIT_DIR/BISECT_NAMES" } bisect_bad() { @@ -121,7 +134,7 @@ bisect_next() { bad=$(git-rev-parse --verify refs/bisect/bad) && good=$(git-rev-parse --sq --revs-only --not \ $(cd "$GIT_DIR" && ls refs/bisect/good-*)) && - rev=$(eval "git-rev-list --bisect $good $bad") || exit + rev=$(eval "git-rev-list --bisect $good $bad -- $(cat $GIT_DIR/BISECT_NAMES)") || exit if [ -z "$rev" ]; then echo "$bad was both good and bad" exit 1 @@ -131,7 +144,7 @@ bisect_next() { git-diff-tree --pretty $rev exit 0 fi - nr=$(eval "git-rev-list $rev $good" | wc -l) || exit + nr=$(eval "git-rev-list $rev $good -- $(cat $GIT_DIR/BISECT_NAMES)" | wc -l) || exit echo "Bisecting: $nr revisions left to test after this" echo "$rev" > "$GIT_DIR/refs/heads/new-bisect" git checkout new-bisect || exit @@ -142,7 +155,8 @@ bisect_next() { bisect_visualize() { bisect_next_check fail - gitk bisect/bad --not `cd "$GIT_DIR/refs" && echo bisect/good-*` + not=`cd "$GIT_DIR/refs" && echo bisect/good-*` + eval gitk bisect/bad --not $not -- $(cat "$GIT_DIR/BISECT_NAMES") } bisect_reset() { @@ -173,7 +187,8 @@ bisect_replay () { test "$bisect" = "git-bisect" || continue case "$command" in start) - bisect_start + cmd="bisect_start $rev" + eval "$cmd" ;; good) echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev" diff --git a/git-clone.sh b/git-clone.sh index c09979a7a4..699205eb66 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -73,7 +73,7 @@ while *,-n) no_checkout=yes ;; *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local) use_local=yes ;; *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared) - local_shared=yes ;; + local_shared=yes; use_local=yes ;; *,-q|*,--quiet) quiet=-q ;; 1,-u|1,--upload-pack) usage ;; *,-u|*,--upload-pack) diff --git a/git-diff.sh b/git-diff.sh index e45f50ec22..b62e58341c 100755 --- a/git-diff.sh +++ b/git-diff.sh @@ -7,8 +7,6 @@ rev=$(git-rev-parse --revs-only --no-flags --sq "$@") || exit flags=$(git-rev-parse --no-revs --flags --sq "$@") files=$(git-rev-parse --no-revs --no-flags --sq "$@") -: ${flags:="'-M' '-p'"} - die () { echo >&2 "$*" exit 1 @@ -25,6 +23,21 @@ case "$rev" in esac esac +# If we do not have --name-status, --name-only nor -r, default to -p. +# If we do not have -B nor -C, default to -M. +case " $flags " in +*" '--name-status' "* | *" '--name-only' "* | *" '-r' "* ) + ;; +*) + flags="$flags'-p' " ;; +esac +case " $flags " in +*" '-"[BCM]* | *" '--find-copies-harder' "*) + ;; # something like -M50. +*) + flags="$flags'-M' " ;; +esac + case "$rev" in ?*' '?*' '?*) echo >&2 "I don't understand" diff --git a/git-format-patch.sh b/git-format-patch.sh index 9b4088045a..1eebe857c0 100755 --- a/git-format-patch.sh +++ b/git-format-patch.sh @@ -5,6 +5,10 @@ . git-sh-setup +# Force diff to run in C locale. +LANG=C LC_ALL=C +export LANG LC_ALL + usage () { echo >&2 "usage: $0"' [-n] [-o dir | --stdout] [--keep-subject] [--mbox] [--check] [--signoff] [-<diff options>...] @@ -202,7 +206,7 @@ process_one () { ;; esac - eval "$(LANG=C LC_ALL=C sed -ne "$whosepatchScript" $commsg)" + eval "$(sed -ne "$whosepatchScript" $commsg)" test "$author,$au" = ",$me" || { mailScript="$mailScript"' a\ @@ -238,9 +242,8 @@ Date: '"$ad" echo git-diff-tree -p $diff_opts "$commit" | git-apply --stat --summary echo - git-cat-file commit "$commit^" | sed -e 's/^tree /applies-to: /' -e q git-diff-tree -p $diff_opts "$commit" - echo "---" + echo "-- " echo "@@GIT_VERSION@@" case "$mbox" in diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh index c3eca8b332..739a07292a 100755 --- a/git-merge-one-file.sh +++ b/git-merge-one-file.sh @@ -79,11 +79,7 @@ case "${1:-.}${2:-.}${3:-.}" in ;; esac - # We reset the index to the first branch, making - # git-diff-file useful - git-update-index --add --cacheinfo "$6" "$2" "$4" - git-checkout-index -u -f -- "$4" && - merge "$4" "$orig" "$src2" + merge "$4" "$orig" "$src2" ret=$? rm -f -- "$orig" "$src2" diff --git a/git-merge-recursive.py b/git-merge-recursive.py index 0129233550..e599b11cc5 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -828,8 +828,6 @@ def processEntry(entry, branch1Name, branch2Name): if cacheOnly: updateFile(False, sha, mode, path) else: - updateFileExt(aSha, aMode, path, - updateCache=True, updateWd=False) updateFileExt(sha, mode, path, updateCache=False, updateWd=True) else: die("ERROR: Fatal merge failure, shouldn't happen.") diff --git a/git-mv.perl b/git-mv.perl index 53046bafd6..b6c0b48818 100755 --- a/git-mv.perl +++ b/git-mv.perl @@ -19,15 +19,9 @@ EOT exit(1); } -# Sanity checks: -my $GIT_DIR = $ENV{'GIT_DIR'} || ".git"; - -unless ( -d $GIT_DIR && -d $GIT_DIR . "/objects" && - -d $GIT_DIR . "/objects/" && -d $GIT_DIR . "/refs") { - print "Error: git repository not found."; - exit(1); -} - +my $GIT_DIR = `git rev-parse --git-dir`; +exit 1 if $?; # rev-parse would have given "not a git dir" message. +chomp($GIT_DIR); our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v); getopts("hnfkv") || usage; diff --git a/git-svnimport.perl b/git-svnimport.perl index 45d77c5bae..65868a91e5 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -35,7 +35,7 @@ our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,$opt_b sub usage() { print STDERR <<END; Usage: ${\basename $0} # fetch/update GIT from SVN - [-o branch-for-HEAD] [-h] [-v] [-l max_num_changes] + [-o branch-for-HEAD] [-h] [-v] [-l max_rev] [-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname] [-d|-D] [-i] [-u] [-s start_chg] [-m] [-M regex] [SVN_URL] END @@ -126,8 +126,9 @@ sub file { package main; use URI; -my $svn = $svn_url; +our $svn = $svn_url; $svn .= "/$svn_dir" if defined $svn_dir; +my $svn2 = SVNconn->new($svn); $svn = SVNconn->new($svn); my $lwp_ua; @@ -198,7 +199,7 @@ $ENV{GIT_INDEX_FILE} = $git_index; my $maxnum = 0; my $last_rev = ""; my $last_branch; -my $current_rev = $opt_s-1; +my $current_rev = $opt_s || 1; unless(-d $git_dir) { system("git-init-db"); die "Cannot init the GIT db at $git_tree: $?\n" if $?; @@ -254,7 +255,7 @@ EOM my($num,$branch,$ref) = split; $branches{$branch}{$num} = $ref; $branches{$branch}{"LAST"} = $ref; - $current_rev = $num if $current_rev < $num; + $current_rev = $num+1 if $current_rev <= $num; } close($B); } @@ -708,17 +709,17 @@ sub commit { print "DONE: $revision $dest $cid\n" if $opt_v; } -my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; -sub _commit_all { - ($changed_paths, $revision, $author, $date, $message, $pool) = @_; +sub commit_all { + # Recursive use of the SVN connection does not work + local $svn = $svn2; + + my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; my %p; while(my($path,$action) = each %$changed_paths) { $p{$path} = [ $action->action,$action->copyfrom_path, $action->copyfrom_rev, $path ]; } $changed_paths = \%p; -} -sub commit_all { my %done; my @col; my $pref; @@ -734,18 +735,12 @@ sub commit_all { } } -while(++$current_rev <= $svn->{'maxrev'}) { - if (defined $opt_l) { - $opt_l--; - if ($opt_l < 0) { - last; - } - } - my $pool=SVN::Pool->new; - $svn->{'svn'}->get_log("/",$current_rev,$current_rev,1,1,1,\&_commit_all,$pool); - $pool->clear; - commit_all(); -} +$opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'}; +print "Fetching from $current_rev to $opt_l ...\n" if $opt_v; + +my $pool=SVN::Pool->new; +$svn->{'svn'}->get_log("/",$current_rev,$opt_l,0,1,1,\&commit_all,$pool); +$pool->clear; unlink($git_index); @@ -297,13 +297,16 @@ proc makewindow {} { global findtype findtypemenu findloc findstring fstring geometry global entries sha1entry sha1string sha1but global maincursor textcursor curtextcursor - global rowctxmenu gaudydiff mergemax + global rowctxmenu mergemax menu .bar .bar add cascade -label "File" -menu .bar.file menu .bar.file .bar.file add command -label "Reread references" -command rereadrefs .bar.file add command -label "Quit" -command doquit + menu .bar.edit + .bar add cascade -label "Edit" -menu .bar.edit + .bar.edit add command -label "Preferences" -command doprefs menu .bar.help .bar add cascade -label "Help" -menu .bar.help .bar.help add command -label "About gitk" -command about @@ -414,25 +417,19 @@ proc makewindow {} { .ctop.cdet add .ctop.cdet.left $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa" - if {$gaudydiff} { - $ctext tag conf hunksep -back blue -fore white - $ctext tag conf d0 -back "#ff8080" - $ctext tag conf d1 -back green - } else { - $ctext tag conf hunksep -fore blue - $ctext tag conf d0 -fore red - $ctext tag conf d1 -fore "#00a000" - $ctext tag conf m0 -fore red - $ctext tag conf m1 -fore blue - $ctext tag conf m2 -fore green - $ctext tag conf m3 -fore purple - $ctext tag conf m4 -fore brown - $ctext tag conf mmax -fore darkgrey - set mergemax 5 - $ctext tag conf mresult -font [concat $textfont bold] - $ctext tag conf msep -font [concat $textfont bold] - $ctext tag conf found -back yellow - } + $ctext tag conf hunksep -fore blue + $ctext tag conf d0 -fore red + $ctext tag conf d1 -fore "#00a000" + $ctext tag conf m0 -fore red + $ctext tag conf m1 -fore blue + $ctext tag conf m2 -fore green + $ctext tag conf m3 -fore purple + $ctext tag conf m4 -fore brown + $ctext tag conf mmax -fore darkgrey + set mergemax 5 + $ctext tag conf mresult -font [concat $textfont bold] + $ctext tag conf msep -font [concat $textfont bold] + $ctext tag conf found -back yellow frame .ctop.cdet.right set cflist .ctop.cdet.right.cfiles @@ -533,7 +530,7 @@ proc click {w} { proc savestuff {w} { global canv canv2 canv3 ctext cflist mainfont textfont - global stuffsaved findmergefiles gaudydiff maxgraphpct + global stuffsaved findmergefiles maxgraphpct global maxwidth if {$stuffsaved} return @@ -543,7 +540,6 @@ proc savestuff {w} { puts $f [list set mainfont $mainfont] puts $f [list set textfont $textfont] puts $f [list set findmergefiles $findmergefiles] - puts $f [list set gaudydiff $gaudydiff] puts $f [list set maxgraphpct $maxgraphpct] puts $f [list set maxwidth $maxwidth] puts $f "set geometry(width) [winfo width .ctop]" @@ -2841,7 +2837,6 @@ proc getblobdiffline {bdf ids} { global diffids blobdifffd ctext curdifftag curtagstart global diffnexthead diffnextnote difffilestart global nextupdate diffinhdr treediffs - global gaudydiff set n [gets $bdf line] if {$n < 0} { @@ -2890,26 +2885,14 @@ proc getblobdiffline {bdf ids} { set diffinhdr 0 } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \ $line match f1l f1c f2l f2c rest]} { - if {$gaudydiff} { - $ctext insert end "\t" hunksep - $ctext insert end " $f1l " d0 " $f2l " d1 - $ctext insert end " $rest \n" hunksep - } else { - $ctext insert end "$line\n" hunksep - } + $ctext insert end "$line\n" hunksep set diffinhdr 0 } else { set x [string range $line 0 0] if {$x == "-" || $x == "+"} { set tag [expr {$x == "+"}] - if {$gaudydiff} { - set line [string range $line 1 end] - } $ctext insert end "$line\n" d$tag } elseif {$x == " "} { - if {$gaudydiff} { - set line [string range $line 1 end] - } $ctext insert end "$line\n" } elseif {$diffinhdr || $x == "\\"} { # e.g. "\ No newline at end of file" @@ -3634,26 +3617,80 @@ proc doquit {} { destroy . } -proc formatdate {d} { - global hours nhours tfd fastdate +proc doprefs {} { + global maxwidth maxgraphpct diffopts findmergefiles + global oldprefs prefstop - if {!$fastdate} { - return [clock format $d -format "%Y-%m-%d %H:%M:%S"] + set top .gitkprefs + set prefstop $top + if {[winfo exists $top]} { + raise $top + return } - set hr [expr {$d / 3600}] - set ms [expr {$d % 3600}] - if {![info exists hours($hr)]} { - set hours($hr) [clock format $d -format "%Y-%m-%d %H"] - set nhours($hr) 0 + foreach v {maxwidth maxgraphpct diffopts findmergefiles} { + set oldprefs($v) [set $v] } - incr nhours($hr) - set minsec [format "%.2d:%.2d" [expr {$ms/60}] [expr {$ms%60}]] - return "$hours($hr):$minsec" + toplevel $top + wm title $top "Gitk preferences" + label $top.ldisp -text "Commit list display options" + grid $top.ldisp - -sticky w -pady 10 + label $top.spacer -text " " + label $top.maxwidthl -text "Maximum graph width (lines)" \ + -font optionfont + spinbox $top.maxwidth -from 0 -to 100 -width 4 -textvariable maxwidth + grid $top.spacer $top.maxwidthl $top.maxwidth -sticky w + label $top.maxpctl -text "Maximum graph width (% of pane)" \ + -font optionfont + spinbox $top.maxpct -from 1 -to 100 -width 4 -textvariable maxgraphpct + grid x $top.maxpctl $top.maxpct -sticky w + checkbutton $top.findm -variable findmergefiles + label $top.findml -text "Include merges for \"Find\" in \"Files\"" \ + -font optionfont + grid $top.findm $top.findml - -sticky w + label $top.ddisp -text "Diff display options" + grid $top.ddisp - -sticky w -pady 10 + label $top.diffoptl -text "Options for diff program" \ + -font optionfont + entry $top.diffopt -width 20 -textvariable diffopts + grid x $top.diffoptl $top.diffopt -sticky w + frame $top.buts + button $top.buts.ok -text "OK" -command prefsok + button $top.buts.can -text "Cancel" -command prefscan + grid $top.buts.ok $top.buts.can + grid columnconfigure $top.buts 0 -weight 1 -uniform a + grid columnconfigure $top.buts 1 -weight 1 -uniform a + grid $top.buts - - -pady 10 -sticky ew +} + +proc prefscan {} { + global maxwidth maxgraphpct diffopts findmergefiles + global oldprefs prefstop + + foreach v {maxwidth maxgraphpct diffopts findmergefiles} { + set $v $oldprefs($v) + } + catch {destroy $prefstop} + unset prefstop +} + +proc prefsok {} { + global maxwidth maxgraphpct + global oldprefs prefstop + + catch {destroy $prefstop} + unset prefstop + if {$maxwidth != $oldprefs(maxwidth) + || $maxgraphpct != $oldprefs(maxgraphpct)} { + redisplay + } +} + +proc formatdate {d} { + return [clock format $d -format "%Y-%m-%d %H:%M:%S"] } # defaults... set datemode 0 -set boldnames 0 set diffopts "-U 5 -p" set wrcomcmd "git-diff-tree --stdin -p --pretty" @@ -3668,7 +3705,6 @@ if {$gitencoding == ""} { set mainfont {Helvetica 9} set textfont {Courier 9} set findmergefiles 0 -set gaudydiff 0 set maxgraphpct 50 set maxwidth 16 set revlistorder 0 @@ -3679,15 +3715,13 @@ set colors {green red blue magenta darkgrey brown orange} catch {source ~/.gitk} set namefont $mainfont -if {$boldnames} { - lappend namefont bold -} + +font create optionfont -family sans-serif -size -12 set revtreeargs {} foreach arg $argv { switch -regexp -- $arg { "^$" { } - "^-b" { set boldnames 1 } "^-d" { set datemode 1 } "^-r" { set revlistorder 1 } default { diff --git a/http-push.c b/http-push.c index c6e782cbed..fe925609b4 100644 --- a/http-push.c +++ b/http-push.c @@ -1008,9 +1008,7 @@ static int unlock_remote(struct active_lock *lock) if (lock->owner != NULL) free(lock->owner); free(lock->url); -/* Freeing the token causes a segfault... free(lock->token); -*/ free(lock); return rc; @@ -1274,6 +1272,9 @@ int main(int argc, char **argv) break; } + if (!remote->url) + usage(http_push_usage); + memset(remote_dir_exists, 0, 256); http_init(); @@ -12,223 +12,56 @@ static int line_termination = '\n'; #define LS_RECURSIVE 1 #define LS_TREE_ONLY 2 static int ls_options = 0; +const char **pathspec; -static struct tree_entry_list root_entry; - -static void prepare_root(unsigned char *sha1) -{ - unsigned char rsha[20]; - unsigned long size; - void *buf; - struct tree *root_tree; - - buf = read_object_with_reference(sha1, "tree", &size, rsha); - free(buf); - if (!buf) - die("Could not read %s", sha1_to_hex(sha1)); - - root_tree = lookup_tree(rsha); - if (!root_tree) - die("Could not read %s", sha1_to_hex(sha1)); - - /* Prepare a fake entry */ - root_entry.directory = 1; - root_entry.executable = root_entry.symlink = 0; - root_entry.mode = S_IFDIR; - root_entry.name = ""; - root_entry.item.tree = root_tree; - root_entry.parent = NULL; -} - -static int prepare_children(struct tree_entry_list *elem) -{ - if (!elem->directory) - return -1; - if (!elem->item.tree->object.parsed) { - struct tree_entry_list *e; - if (parse_tree(elem->item.tree)) - return -1; - /* Set up the parent link */ - for (e = elem->item.tree->entries; e; e = e->next) - e->parent = elem; - } - return 0; -} +static const char ls_tree_usage[] = + "git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]"; -static struct tree_entry_list *find_entry(const char *path, char *pathbuf) +static int show_tree(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage) { - const char *next, *slash; - int len; - struct tree_entry_list *elem = &root_entry, *oldelem = NULL; - - *(pathbuf) = '\0'; - - /* Find tree element, descending from root, that - * corresponds to the named path, lazily expanding - * the tree if possible. - */ - - while (path) { - /* The fact we still have path means that the caller - * wants us to make sure that elem at this point is a - * directory, and possibly descend into it. Even what - * is left is just trailing slashes, we loop back to - * here, and this call to prepare_children() will - * catch elem not being a tree. Nice. - */ - if (prepare_children(elem)) - return NULL; - - slash = strchr(path, '/'); - if (!slash) { - len = strlen(path); - next = NULL; - } - else { - next = slash + 1; - len = slash - path; - } - if (len) { - if (oldelem) { - pathbuf += sprintf(pathbuf, "%s/", oldelem->name); - } - - /* (len == 0) if the original path was "drivers/char/" - * and we have run already two rounds, having elem - * pointing at the drivers/char directory. - */ - elem = elem->item.tree->entries; - while (elem) { - if ((strlen(elem->name) == len) && - !strncmp(elem->name, path, len)) { - /* found */ + const char *type = "blob"; + + if (S_ISDIR(mode)) { + const char **s; + if (ls_options & LS_RECURSIVE) + return READ_TREE_RECURSIVE; + s = pathspec; + if (s) { + for (;;) { + const char *spec = *s++; + int len, speclen; + + if (!spec) break; - } - elem = elem->next; + if (strncmp(base, spec, baselen)) + continue; + len = strlen(pathname); + spec += baselen; + speclen = strlen(spec); + if (speclen <= len) + continue; + if (memcmp(pathname, spec, len)) + continue; + return READ_TREE_RECURSIVE; } - if (!elem) - return NULL; - - oldelem = elem; } - path = next; + type = "tree"; } - return elem; -} - -static const char *entry_type(struct tree_entry_list *e) -{ - return (e->directory ? "tree" : "blob"); -} - -static const char *entry_hex(struct tree_entry_list *e) -{ - return sha1_to_hex(e->directory - ? e->item.tree->object.sha1 - : e->item.blob->object.sha1); -} - -/* forward declaration for mutually recursive routines */ -static int show_entry(struct tree_entry_list *, int, char *pathbuf); - -static int show_children(struct tree_entry_list *e, int level, char *pathbuf) -{ - int oldlen = strlen(pathbuf); - - if (e != &root_entry) - sprintf(pathbuf + oldlen, "%s/", e->name); - - if (prepare_children(e)) - die("internal error: ls-tree show_children called with non tree"); - e = e->item.tree->entries; - while (e) { - show_entry(e, level, pathbuf); - e = e->next; - } - - pathbuf[oldlen] = '\0'; - + printf("%06o %s %s\t", mode, type, sha1_to_hex(sha1)); + write_name_quoted(base, baselen, pathname, line_termination, stdout); + putchar(line_termination); return 0; } -static int show_entry(struct tree_entry_list *e, int level, char *pathbuf) -{ - int err = 0; - - if (e != &root_entry) { - int pathlen = strlen(pathbuf); - printf("%06o %s %s ", - e->mode, entry_type(e), entry_hex(e)); - write_name_quoted(pathbuf, pathlen, e->name, - line_termination, stdout); - putchar(line_termination); - } - - if (e->directory) { - /* If this is a directory, we have the following cases: - * (1) This is the top-level request (explicit path from the - * command line, or "root" if there is no command line). - * a. Without any flag. We show direct children. We do not - * recurse into them. - * b. With -r. We do recurse into children. - * c. With -d. We do not recurse into children. - * (2) We came here because our caller is either (1-a) or - * (1-b). - * a. Without any flag. We do not show our children (which - * are grandchildren for the original request). - * b. With -r. We continue to recurse into our children. - * c. With -d. We should not have come here to begin with. - */ - if (level == 0 && !(ls_options & LS_TREE_ONLY)) - /* case (1)-a and (1)-b */ - err = err | show_children(e, level+1, pathbuf); - else if (level && ls_options & LS_RECURSIVE) - /* case (2)-b */ - err = err | show_children(e, level+1, pathbuf); - } - return err; -} - -static int list_one(const char *path) -{ - int err = 0; - char pathbuf[MAXPATHLEN + 1]; - struct tree_entry_list *e = find_entry(path, pathbuf); - if (!e) { - /* traditionally ls-tree does not complain about - * missing path. We may change this later to match - * what "/bin/ls -a" does, which is to complain. - */ - return err; - } - err = err | show_entry(e, 0, pathbuf); - return err; -} - -static int list(const char **path) -{ - int i; - int err = 0; - for (i = 0; path[i]; i++) - err = err | list_one(path[i]); - return err; -} - -static const char ls_tree_usage[] = - "git-ls-tree [-d] [-r] [-z] <tree-ish> [path...]"; - int main(int argc, const char **argv) { - static const char *path0[] = { "", NULL }; - const char **path; + const char *prefix; unsigned char sha1[20]; - int nongit = 0; - const char *prefix = setup_git_directory_gently(&nongit); - - if (prefix) - path0[0] = prefix; + char *buf; + unsigned long size; + prefix = setup_git_directory(); while (1 < argc && argv[1][0] == '-') { switch (argv[1][1]) { case 'z': @@ -251,13 +84,11 @@ int main(int argc, const char **argv) if (get_sha1(argv[1], sha1) < 0) usage(ls_tree_usage); - if (argc == 2) - path = path0; - else - path = get_pathspec(prefix, argv + 2); + pathspec = get_pathspec(prefix, argv + 2); + buf = read_object_with_reference(sha1, "tree", &size, NULL); + if (!buf) + die("not a tree object"); + read_tree_recursive(buf, size, "", 0, 0, pathspec, show_tree); - prepare_root(sha1); - if (list(path) < 0) - die("list failed"); return 0; } diff --git a/rev-list.c b/rev-list.c index e17f928061..8020d974f2 100644 --- a/rev-list.c +++ b/rev-list.c @@ -350,7 +350,8 @@ static int count_distance(struct commit_list *entry) if (commit->object.flags & (UNINTERESTING | COUNTED)) break; - nr++; + if (!paths || (commit->object.flags & TREECHANGE)) + nr++; commit->object.flags |= COUNTED; p = commit->parents; entry = p; @@ -362,6 +363,7 @@ static int count_distance(struct commit_list *entry) } } } + return nr; } @@ -382,15 +384,20 @@ static struct commit_list *find_bisection(struct commit_list *list) nr = 0; p = list; while (p) { - nr++; + if (!paths || (p->item->object.flags & TREECHANGE)) + nr++; p = p->next; } closest = 0; best = list; - p = list; - while (p) { - int distance = count_distance(p); + for (p = list; p; p = p->next) { + int distance; + + if (paths && !(p->item->object.flags & TREECHANGE)) + continue; + + distance = count_distance(p); clear_distance(list); if (nr - distance < distance) distance = nr - distance; @@ -398,7 +405,6 @@ static struct commit_list *find_bisection(struct commit_list *list) best = p; closest = distance; } - p = p->next; } if (best) best->next = NULL; @@ -131,7 +131,7 @@ const char *setup_git_directory_gently(int *nongit_ok) if (validate_symref(path)) goto bad_dir_environ; if (getenv(DB_ENVIRONMENT)) { - if (access(DB_ENVIRONMENT, X_OK)) + if (access(getenv(DB_ENVIRONMENT), X_OK)) goto bad_dir_environ; } else { diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index dff7d69163..22bdacaf78 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -126,19 +126,18 @@ test_expect_success \ 'git-ls-tree output for a known tree.' \ 'diff current expected' +# This changed in ls-tree pathspec change -- recursive does +# not show tree nodes anymore. test_expect_success \ 'showing tree with git-ls-tree -r' \ 'git-ls-tree -r $tree >current' cat >expected <<\EOF 100644 blob f87290f8eb2cbbea7857214459a0739927eab154 path0 120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01 path0sym -040000 tree 58a09c23e2ca152193f2786e06986b7b6712bdbe path2 100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 path2/file2 120000 blob d8ce161addc5173867a3c3c730924388daedbc38 path2/file2sym -040000 tree 21ae8269cacbe57ae09138dcc3a2887f904d02b3 path3 100644 blob 0aa34cae68d0878578ad119c86ca2b5ed5b28376 path3/file3 120000 blob 8599103969b43aff7e430efea79ca4636466794f path3/file3sym -040000 tree 3c5e5399f3a333eddecce7a9b9465b63f65f51e2 path3/subp3 100644 blob 00fb5908cb97c2564a9783c0c64087333b3b464f path3/subp3/file3 120000 blob 6649a1ebe9e9f1c553b66f5a6e74136a07ccc57c path3/subp3/file3sym EOF diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh index c6ce56c86b..ae086755ea 100755 --- a/t/t3100-ls-tree-restrict.sh +++ b/t/t3100-ls-tree-restrict.sh @@ -54,8 +54,6 @@ test_expect_success \ cat >expected <<\EOF && 100644 blob X path0 120000 blob X path1 -040000 tree X path2 -040000 tree X path2/baz 100644 blob X path2/baz/b 120000 blob X path2/bazbo 100644 blob X path2/foo @@ -70,12 +68,14 @@ EOF test_output' +# it used to be path1 and then path0, but with pathspec semantics +# they are shown in canonical order. test_expect_success \ 'ls-tree filtered with path1 path0' \ 'git-ls-tree $tree path1 path0 >current && cat >expected <<\EOF && -120000 blob X path1 100644 blob X path0 +120000 blob X path1 EOF test_output' @@ -86,45 +86,34 @@ test_expect_success \ EOF test_output' +# It used to show path2 and its immediate children but +# with pathspec semantics it shows only path2 test_expect_success \ 'ls-tree filtered with path2' \ 'git-ls-tree $tree path2 >current && cat >expected <<\EOF && 040000 tree X path2 -040000 tree X path2/baz -120000 blob X path2/bazbo -100644 blob X path2/foo -EOF - test_output' - -test_expect_success \ - 'ls-tree filtered with path2/baz' \ - 'git-ls-tree $tree path2/baz >current && - cat >expected <<\EOF && -040000 tree X path2/baz -100644 blob X path2/baz/b EOF test_output' +# ... and path2/ shows the children. test_expect_success \ - 'ls-tree filtered with path2' \ - 'git-ls-tree $tree path2 >current && + 'ls-tree filtered with path2/' \ + 'git-ls-tree $tree path2/ >current && cat >expected <<\EOF && -040000 tree X path2 040000 tree X path2/baz 120000 blob X path2/bazbo 100644 blob X path2/foo EOF test_output' +# The same change -- exact match does not show children of +# path2/baz test_expect_success \ - 'ls-tree filtered with path2/' \ - 'git-ls-tree $tree path2/ >current && + 'ls-tree filtered with path2/baz' \ + 'git-ls-tree $tree path2/baz >current && cat >expected <<\EOF && -040000 tree X path2 040000 tree X path2/baz -120000 blob X path2/bazbo -100644 blob X path2/foo EOF test_output' diff --git a/t/t3101-ls-tree-dirname.sh b/t/t3101-ls-tree-dirname.sh index 5410368348..d78deb1e71 100644 --- a/t/t3101-ls-tree-dirname.sh +++ b/t/t3101-ls-tree-dirname.sh @@ -59,24 +59,16 @@ test_expect_success \ EOF test_output' +# Recursive does not show tree nodes anymore... test_expect_success \ 'ls-tree recursive' \ 'git-ls-tree -r $tree >current && cat >expected <<\EOF && 100644 blob X 1.txt 100644 blob X 2.txt -040000 tree X path0 -040000 tree X path0/a -040000 tree X path0/a/b -040000 tree X path0/a/b/c 100644 blob X path0/a/b/c/1.txt -040000 tree X path1 -040000 tree X path1/b -040000 tree X path1/b/c 100644 blob X path1/b/c/1.txt -040000 tree X path2 100644 blob X path2/1.txt -040000 tree X path3 100644 blob X path3/1.txt 100644 blob X path3/2.txt EOF @@ -110,41 +102,27 @@ test_expect_success \ EOF test_output' +# I am not so sure about this one after ls-tree doing pathspec match. +# Having both path0/a and path0/a/b/c makes path0/a redundant, and +# it behaves as if path0/a/b/c, path1/b/c, path2 and path3 are specified. test_expect_success \ 'ls-tree filter directories' \ 'git-ls-tree $tree path3 path2 path0/a/b/c path1/b/c path0/a >current && cat >expected <<\EOF && -040000 tree X path3 -100644 blob X path3/1.txt -100644 blob X path3/2.txt -040000 tree X path2 -100644 blob X path2/1.txt 040000 tree X path0/a/b/c -100644 blob X path0/a/b/c/1.txt 040000 tree X path1/b/c -100644 blob X path1/b/c/1.txt -040000 tree X path0/a -040000 tree X path0/a/b +040000 tree X path2 +040000 tree X path3 EOF test_output' +# Again, duplicates are filtered away so this is equivalent to +# having 1.txt and path3 test_expect_success \ 'ls-tree filter odd names' \ 'git-ls-tree $tree 1.txt /1.txt //1.txt path3/1.txt /path3/1.txt //path3//1.txt path3 /path3/ path3// >current && cat >expected <<\EOF && 100644 blob X 1.txt -100644 blob X 1.txt -100644 blob X 1.txt -100644 blob X path3/1.txt -100644 blob X path3/1.txt -100644 blob X path3/1.txt -040000 tree X path3 -100644 blob X path3/1.txt -100644 blob X path3/2.txt -040000 tree X path3 -100644 blob X path3/1.txt -100644 blob X path3/2.txt -040000 tree X path3 100644 blob X path3/1.txt 100644 blob X path3/2.txt EOF diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh new file mode 100755 index 0000000000..43d74c502e --- /dev/null +++ b/t/t7001-mv.sh @@ -0,0 +1,27 @@ +#!/bin/sh + +test_description='git-mv in subdirs' +. ./test-lib.sh + +test_expect_success \ + 'prepare reference tree' \ + 'mkdir path0 path1 && + cp ../../COPYING path0/COPYING && + git-add path0/COPYING && + git-commit -m add -a' + +test_expect_success \ + 'moving the file' \ + 'cd path0 && git-mv COPYING ../path1/COPYING' + +# in path0 currently +test_expect_success \ + 'commiting the change' \ + 'cd .. && git-commit -m move -a' + +test_expect_success \ + 'checking the commit' \ + 'git-diff-tree -r -M --name-status HEAD^ HEAD | \ + grep -E "^R100.+path0/COPYING.+path1/COPYING"' + +test_done @@ -9,9 +9,16 @@ const char *tree_type = "tree"; static int read_one_entry(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage) { - int len = strlen(pathname); - unsigned int size = cache_entry_size(baselen + len); - struct cache_entry *ce = xmalloc(size); + int len; + unsigned int size; + struct cache_entry *ce; + + if (S_ISDIR(mode)) + return READ_TREE_RECURSIVE; + + len = strlen(pathname); + size = cache_entry_size(baselen + len); + ce = xmalloc(size); memset(ce, 0, size); @@ -67,9 +74,10 @@ static int match_tree_entry(const char *base, int baselen, const char *path, uns return 0; } -static int read_tree_recursive(void *buffer, unsigned long size, - const char *base, int baselen, - int stage, const char **match) +int read_tree_recursive(void *buffer, unsigned long size, + const char *base, int baselen, + int stage, const char **match, + read_tree_fn_t fn) { while (size) { int len = strlen(buffer)+1; @@ -86,6 +94,14 @@ static int read_tree_recursive(void *buffer, unsigned long size, if (!match_tree_entry(base, baselen, path, mode, match)) continue; + switch (fn(sha1, base, baselen, path, mode, stage)) { + case 0: + continue; + case READ_TREE_RECURSIVE: + break;; + default: + return -1; + } if (S_ISDIR(mode)) { int retval; int pathlen = strlen(path); @@ -106,22 +122,20 @@ static int read_tree_recursive(void *buffer, unsigned long size, retval = read_tree_recursive(eltbuf, eltsize, newbase, baselen + pathlen + 1, - stage, match); + stage, match, fn); free(eltbuf); free(newbase); if (retval) return -1; continue; } - if (read_one_entry(sha1, base, baselen, path, mode, stage) < 0) - return -1; } return 0; } int read_tree(void *buffer, unsigned long size, int stage, const char **match) { - return read_tree_recursive(buffer, size, "", 0, stage, match); + return read_tree_recursive(buffer, size, "", 0, stage, match, read_one_entry); } struct tree *lookup_tree(const unsigned char *sha1) @@ -35,4 +35,13 @@ int parse_tree(struct tree *tree); /* Parses and returns the tree in the given ent, chasing tags and commits. */ struct tree *parse_tree_indirect(const unsigned char *sha1); +#define READ_TREE_RECURSIVE 1 +typedef int (*read_tree_fn_t)(unsigned char *, const char *, int, const char *, unsigned int, int); + +extern int read_tree_recursive(void *buffer, unsigned long size, + const char *base, int baselen, + int stage, const char **match, + read_tree_fn_t fn); + + #endif /* TREE_H */ |