From b5c2f30689d66761ce4e8a5e69c9924c0c389233 Mon Sep 17 00:00:00 2001 From: Sven Verdoolaege Date: Tue, 29 Nov 2005 22:15:51 +0100 Subject: [PATCH] gitk: add Update menu item. Update will redraw the commits if any commits have been added to any of the selected heads. The new commits appear on the top. Signed-off-by: Sven Verdoolaege Signed-off-by: Paul Mackerras --- gitk | 176 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 142 insertions(+), 34 deletions(-) diff --git a/gitk b/gitk index a847ef69c7..db61a15da1 100755 --- a/gitk +++ b/gitk @@ -16,8 +16,24 @@ proc gitdir {} { } } +proc parse_args {rargs} { + global parsed_args + + if [catch { + set parse_args [concat --default HEAD $rargs] + set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"] + }] { + # if git-rev-parse failed for some reason... + if {$rargs == {}} { + set rargs HEAD + } + set parsed_args $rargs + } + return $parsed_args +} + proc getcommits {rargs} { - global commits commfd phase canv mainfont env + global oldcommits commits commfd phase canv mainfont env global startmsecs nextupdate ncmupdate global ctext maincursor textcursor leftover gitencoding @@ -27,21 +43,13 @@ proc getcommits {rargs} { error_popup "Cannot find the git directory \"$gitdir\"." exit 1 } + set oldcommits {} set commits {} set phase getcommits set startmsecs [clock clicks -milliseconds] set nextupdate [expr {$startmsecs + 100}] set ncmupdate 1 - if [catch { - set parse_args [concat --default HEAD $rargs] - set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"] - }] { - # if git-rev-parse failed for some reason... - if {$rargs == {}} { - set rargs HEAD - } - set parsed_args $rargs - } + set parsed_args [parse_args $rargs] if [catch { set commfd [open "|git-rev-list --header --topo-order --parents $parsed_args" r] } err] { @@ -59,9 +67,10 @@ proc getcommits {rargs} { } proc getcommitlines {commfd} { - global commits parents cdate children + global oldcommits commits parents cdate children nchildren global commitlisted phase nextupdate global stopped redisplaying leftover + global canv set stuff [read $commfd] if {$stuff == {}} { @@ -119,10 +128,18 @@ proc getcommitlines {commfd} { set id [lindex $ids 0] set olds [lrange $ids 1 end] set cmit [string range $cmit [expr {$j + 1}] end] + if {$phase == "updatecommits"} { + $canv delete all + set oldcommits $commits + set commits {} + unset children + unset nchildren + set phase getcommits + } lappend commits $id set commitlisted($id) 1 parsecommit $id $cmit 1 [lrange $ids 1 end] - drawcommit $id + drawcommit $id 1 if {[clock clicks -milliseconds] >= $nextupdate} { doupdate 1 } @@ -132,7 +149,7 @@ proc getcommitlines {commfd} { set stopped 0 set phase "getcommits" foreach id $commits { - drawcommit $id + drawcommit $id 1 if {$stopped} break if {[clock clicks -milliseconds] >= $nextupdate} { doupdate 1 @@ -168,16 +185,9 @@ proc readcommit {id} { parsecommit $id $contents 0 {} } -proc parsecommit {id contents listed olds} { - global commitinfo children nchildren parents nparents cdate ncleft +proc updatechildren {id olds} { + global children nchildren parents nparents ncleft - set inhdr 1 - set comment {} - set headline {} - set auname {} - set audate {} - set comname {} - set comdate {} if {![info exists nchildren($id)]} { set children($id) {} set nchildren($id) 0 @@ -196,6 +206,19 @@ proc parsecommit {id contents listed olds} { incr ncleft($p) } } +} + +proc parsecommit {id contents listed olds} { + global commitinfo cdate + + set inhdr 1 + set comment {} + set headline {} + set auname {} + set audate {} + set comname {} + set comdate {} + updatechildren $id $olds set hdrend [string first "\n\n" $contents] if {$hdrend < 0} { # should never happen... @@ -243,6 +266,9 @@ proc readrefs {} { global tagids idtags headids idheads tagcontents global otherrefids idotherrefs + foreach v {tagids idtags headids idheads otherrefids idotherrefs} { + catch {unset $v} + } set refd [open [list | git-ls-remote [gitdir]] r] while {0 <= [set n [gets $refd line]]} { if {![regexp {^([0-9a-f]{40}) refs/([^^]*)$} $line \ @@ -292,7 +318,7 @@ proc error_popup msg { tkwait window $w } -proc makewindow {} { +proc makewindow {rargs} { global canv canv2 canv3 linespc charspc ctext cflist textfont global findtype findtypemenu findloc findstring fstring geometry global entries sha1entry sha1string sha1but @@ -302,6 +328,7 @@ proc makewindow {} { menu .bar .bar add cascade -label "File" -menu .bar.file menu .bar.file + .bar.file add command -label "Update" -command [list updatecommits $rargs] .bar.file add command -label "Reread references" -command rereadrefs .bar.file add command -label "Quit" -command doquit menu .bar.edit @@ -1412,8 +1439,9 @@ proc decidenext {{noread 0}} { return $level } -proc drawcommit {id} { +proc drawcommit {id reading} { global phase todo nchildren datemode nextupdate revlistorder + global numcommits ncmupdate displayorder todo onscreen global numcommits ncmupdate displayorder todo onscreen parents if {$phase != "incrdraw"} { @@ -1451,20 +1479,29 @@ proc drawcommit {id} { } } } - drawmore 1 + drawmore $reading } proc finishcommits {} { - global phase + global phase oldcommits commits global canv mainfont ctext maincursor textcursor + global parents - if {$phase != "incrdraw"} { + if {$phase == "incrdraw" || $phase == "removecommits"} { + foreach id $oldcommits { + lappend commits $id + updatechildren $id $parents($id) + drawcommit $id 0 + } + set oldcommits {} + drawrest + } elseif {$phase == "updatecommits"} { + set phase {} + } else { $canv delete all $canv create text 3 3 -anchor nw -text "No commits selected" \ -font $mainfont -tags textitems set phase {} - } else { - drawrest } . config -cursor $maincursor settextcursor $textcursor @@ -3578,9 +3615,6 @@ proc rereadrefs {} { set ref($id) [listrefs $id] } } - foreach v {tagids idtags headids idheads otherrefids idotherrefs} { - catch {unset $v} - } readrefs set refids [lsort -unique [concat $refids [array names idtags] \ [array names idheads] [array names idotherrefs]]] @@ -3592,6 +3626,80 @@ proc rereadrefs {} { } } +proc updatecommits {rargs} { + global commitlisted commfd phase + global startmsecs nextupdate ncmupdate + global idtags idheads idotherrefs + global leftover + global parsed_args + global canv + global oldcommits commits + global parents nchildren children ncleft + + set old_args $parsed_args + parse_args $rargs + + foreach id $old_args { + if {![regexp {^[0-9a-f]{40}$} $id]} continue + if {[info exists oldref($id)]} continue + set oldref($id) $id + lappend ignoreold "^$id" + } + foreach id $parsed_args { + if {![regexp {^[0-9a-f]{40}$} $id]} continue + if {[info exists ref($id)]} continue + set ref($id) $id + lappend ignorenew "^$id" + } + + foreach a $old_args { + if {![info exists ref($a)]} { + lappend ignorenew $a + } + } + + set phase updatecommits + set removed_commits [split [eval exec git-rev-list $ignorenew] "\n" ] + if {[llength $removed_commits] > 0} { + $canv delete all + set oldcommits {} + foreach c $commits { + if {[lsearch $c $removed_commits] < 0} { + lappend oldcommits $c + } else { + unset commitlisted($c) + } + } + set commits {} + unset children + unset nchildren + set phase removecommits + } + + set args {} + foreach a $parsed_args { + if {![info exists oldref($a)]} { + lappend args $a + } + } + + readrefs + if [catch { + set commfd [open "|git-rev-list --header --topo-order --parents $ignoreold $args" r] + } err] { + puts stderr "Error executing git-rev-list: $err" + exit 1 + } + set startmsecs [clock clicks -milliseconds] + set nextupdate [expr $startmsecs + 100] + set ncmupdate 1 + set leftover {} + fconfigure $commfd -blocking 0 -translation lf + fileevent $commfd readable [list getcommitlines $commfd] + . config -cursor watch + settextcursor watch +} + proc showtag {tag isnew} { global ctext cflist tagcontents tagids linknum @@ -3738,6 +3846,6 @@ set redisplaying 0 set stuffsaved 0 set patchnum 0 setcoords -makewindow +makewindow $revtreeargs readrefs getcommits $revtreeargs -- cgit v1.2.3 From 38ad0910a0fad012943e6e87f1fc0b1de5851d91 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Thu, 1 Dec 2005 22:42:46 +1100 Subject: gitk: Factored out some common code into a new start_rev_list procedure Signed-off-by: Paul Mackerras --- gitk | 52 ++++++++++++++++++++++------------------------------ 1 file changed, 22 insertions(+), 30 deletions(-) diff --git a/gitk b/gitk index db61a15da1..42e96d0e49 100755 --- a/gitk +++ b/gitk @@ -32,26 +32,16 @@ proc parse_args {rargs} { return $parsed_args } -proc getcommits {rargs} { - global oldcommits commits commfd phase canv mainfont env +proc start_rev_list {rlargs} { global startmsecs nextupdate ncmupdate - global ctext maincursor textcursor leftover gitencoding + global commfd leftover gitencoding - # check that we can find a .git directory somewhere... - set gitdir [gitdir] - if {![file isdirectory $gitdir]} { - error_popup "Cannot find the git directory \"$gitdir\"." - exit 1 - } - set oldcommits {} - set commits {} - set phase getcommits set startmsecs [clock clicks -milliseconds] set nextupdate [expr {$startmsecs + 100}] set ncmupdate 1 - set parsed_args [parse_args $rargs] if [catch { - set commfd [open "|git-rev-list --header --topo-order --parents $parsed_args" r] + set commfd [open [concat | git-rev-list --header --topo-order \ + --parents $rlargs] r] } err] { puts stderr "Error executing git-rev-list: $err" exit 1 @@ -59,11 +49,26 @@ proc getcommits {rargs} { set leftover {} fconfigure $commfd -blocking 0 -translation lf -encoding $gitencoding fileevent $commfd readable [list getcommitlines $commfd] + . config -cursor watch + settextcursor watch +} + +proc getcommits {rargs} { + global oldcommits commits phase canv mainfont env + + # check that we can find a .git directory somewhere... + set gitdir [gitdir] + if {![file isdirectory $gitdir]} { + error_popup "Cannot find the git directory \"$gitdir\"." + exit 1 + } + set oldcommits {} + set commits {} + set phase getcommits + start_rev_list [parse_args $rargs] $canv delete all $canv create text 3 3 -anchor nw -text "Reading commits..." \ -font $mainfont -tags textitems - . config -cursor watch - settextcursor watch } proc getcommitlines {commfd} { @@ -3684,20 +3689,7 @@ proc updatecommits {rargs} { } readrefs - if [catch { - set commfd [open "|git-rev-list --header --topo-order --parents $ignoreold $args" r] - } err] { - puts stderr "Error executing git-rev-list: $err" - exit 1 - } - set startmsecs [clock clicks -milliseconds] - set nextupdate [expr $startmsecs + 100] - set ncmupdate 1 - set leftover {} - fconfigure $commfd -blocking 0 -translation lf - fileevent $commfd readable [list getcommitlines $commfd] - . config -cursor watch - settextcursor watch + start_rev_list [concat $ignoreold $args] } proc showtag {tag isnew} { -- cgit v1.2.3 From 4c353e890c0107a8e733ab11634da21844ec38ba Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Sun, 4 Dec 2005 11:59:37 -0500 Subject: Warn when send-pack does nothing If you try to push into an empty repository with no ref arguments to git push, it doesn't do anything and doesn't say anything. This adds a warning when send-pack isn't going to push anything, so you don't assume that it silently did what you wanted. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- send-pack.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/send-pack.c b/send-pack.c index 2a14b00845..f61c15c820 100644 --- a/send-pack.c +++ b/send-pack.c @@ -190,6 +190,12 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec) if (match_refs(local_refs, remote_refs, &remote_tail, nr_refspec, refspec, send_all)) return -1; + + if (!remote_refs) { + fprintf(stderr, "No refs in common and none specified; doing nothing.\n"); + return 0; + } + /* * Finally, tell the other end! */ -- cgit v1.2.3 From 3a2674337c12e958f8c697af991a0ef6c06ddd4d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 14:41:35 -0800 Subject: compat/setenv: do not free what we fed putenv(3). Signed-off-by: Junio C Hamano --- compat/setenv.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compat/setenv.c b/compat/setenv.c index 94acd2da9e..b7d7678598 100644 --- a/compat/setenv.c +++ b/compat/setenv.c @@ -16,7 +16,7 @@ int gitsetenv(const char *name, const char *value, int replace) namelen = strlen(name); valuelen = strlen(value); - envstr = malloc((namelen + valuelen + 2) * sizeof(char)); + envstr = malloc((namelen + valuelen + 2)); if (!envstr) return -1; memcpy(envstr, name, namelen); @@ -25,7 +25,11 @@ int gitsetenv(const char *name, const char *value, int replace) envstr[namelen + valuelen + 1] = 0; out = putenv(envstr); + /* putenv(3) makes the argument string part of the environment, + * and changing that string modifies the environment --- which + * means we do not own that storage anymore. Do not free + * envstr. + */ - free(envstr); return out; } -- cgit v1.2.3 From 9a79c5a8b4e280601bcbeeed22e1e4968d06c10e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 14:59:58 -0800 Subject: git.c: two fixes, gitsetenv type and off-by-one error. gitsetenv as implemented in compat/setenv.c takes two const char* and int; match that. Also fix an incorrect attempt in prepend_to_path() to NUL-terminate the string which stuffed the NUL character at one past the end of allocation, and was not needed to begin with (we copy the old_path string including the NUL which terminates it). Signed-off-by: Junio C Hamano --- git.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/git.c b/git.c index 619f25acf5..0975fc7ac2 100644 --- a/git.c +++ b/git.c @@ -14,7 +14,7 @@ #endif #ifdef NO_SETENV -extern int gitsetenv(char *name, char *value, int overwrite); +extern int gitsetenv(const char *, const char *, int); #endif static const char git_usage[] = @@ -192,7 +192,6 @@ static void prepend_to_path(const char *dir, int len) path_len = len + strlen(old_path) + 1; path = malloc(path_len + 1); - path[path_len + 1] = '\0'; memcpy(path, dir, len); path[len] = ':'; -- cgit v1.2.3 From 7b9b4c452c793d0f8e3ff9f0b7fe526448fc314a Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Mon, 5 Dec 2005 00:31:08 +0100 Subject: Update the git-ls-tree documentation This patch aims to freshen up a bit the git-ls-tree documentation. It hints that the list of paths are in fact patterns to be matched, explains the new -t, --name-only and --name-status options, corrects the original autorship information to refer to yours sincerely, corrects several grammar mistakes, etc. Since the documentation still deserves some significant work (at least proper description of the pattern matching), I also added the stub notice. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- Documentation/git-ls-tree.txt | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt index ba0438e9ad..b92a8b2db1 100644 --- a/Documentation/git-ls-tree.txt +++ b/Documentation/git-ls-tree.txt @@ -8,12 +8,15 @@ git-ls-tree - Lists the contents of a tree object. SYNOPSIS -------- -'git-ls-tree' [-d] [-r] [-z] [paths...] +'git-ls-tree' [-d] [-r] [-t] [-z] [--name-only] [--name-status] [paths...] DESCRIPTION ----------- -Lists the contents of a tree object, like what "/bin/ls -a" does -in the current working directory. +Lists the contents of a given tree object, like what "/bin/ls -a" does +in the current working directory. Note that the usage is subtly different, +though - 'paths' denote just a list of patterns to match, e.g. so specifying +directory name (without '-r') will behave differently, and order of the +arguments does not matter. OPTIONS ------- @@ -21,36 +24,48 @@ OPTIONS Id of a tree-ish. -d:: - show only the named tree entry itself, not its children + Show only the named tree entry itself, not its children. -r:: - recurse into sub-trees + Recurse into sub-trees. + +-t:: + Show tree entries even when going to recurse them. Has no effect + if '-r' was not passed. '-d' implies '-t'. -z:: - \0 line termination on output + \0 line termination on output. + +--name-only:: +--name-status:: + List only filenames (instead of the "long" output), one per line. paths:: - When paths are given, show them. Otherwise implicitly - uses the root level of the tree as the sole path argument. + When paths are given, show them (note that this isn't really raw + pathnames, but rather a list of patterns to match). Otherwise + implicitly uses the root level of the tree as the sole path argument. Output Format ------------- SP SP TAB -When `-z` option is not used, TAB, LF, and backslash characters -in pathnames are represented as `\t`, `\n`, and `\\`, -respectively. +When the `-z` option is not used, TAB, LF, and backslash characters +in pathnames are represented as `\t`, `\n`, and `\\`, respectively. Author ------ -Written by Linus Torvalds -Completely rewritten from scratch by Junio C Hamano +Written by Petr Baudis +Completely rewritten from scratch by Junio C Hamano , +another major rewrite by Linus Torvalds Documentation -------------- -Documentation by David Greaves, Junio C Hamano and the git-list . +Documentation by David Greaves, Junio C Hamano and the git-list +. + +This manual page is a stub. You can help the git documentation by expanding it. GIT --- -- cgit v1.2.3 From 287f860054345505e4f737466279efa6c3ff04b5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 15:58:50 -0800 Subject: show-branch: allow glob pattern to name branches to show. With this, you can say "git-show-branch topic/* master" to show all the topic branches you have under .git/refs/heads/topic/ and your master branch. Another example is "git-show-branch --list v1.0*" to show all the v1.0 tags. You can disambiguate by saying "heads/topic/*" to show only topic branches if you have tags under .git/refs/tags/topic/ as well. Signed-off-by: Junio C Hamano --- Documentation/git-show-branch.txt | 23 ++++++++---- show-branch.c | 76 ++++++++++++++++++++++++++++++++++----- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index c6c97b21c3..304101d818 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -7,18 +7,29 @@ git-show-branch - Show branches and their commits. SYNOPSIS -------- -'git-show-branch [--all] [--heads] [--tags] [--more= | --list | --independent | --merge-base] [--no-name | --sha1-name] ...' +'git-show-branch [--all] [--heads] [--tags] [--more= | --list | --independent | --merge-base] [--no-name | --sha1-name] [ | ]...' DESCRIPTION ----------- -Shows the head commits from the named (or all refs under -$GIT_DIR/refs/heads), and displays concise list of commit logs -to show their relationship semi-visually. + +Shows the commit ancestry graph starting from the commits named +with s or s (or all refs under $GIT_DIR/refs/heads +and/or $GIT_DIR/refs/tags) semi-visually. + +It cannot show more than 29 branches and commits at a time. + OPTIONS ------- -:: - Name of the reference under $GIT_DIR/refs/. +:: + Arbitrary extended SHA1 expression (see `git-rev-parse`) + that typically names a branch HEAD or a tag. + +:: + A glob pattern that matches branch or tag names under + $GIT_DIR/refs. For example, if you have many topic + branches under $GIT_DIR/refs/heads/topic, giving + `topic/*` would show all of them. --all --heads --tags:: Show all refs under $GIT_DIR/refs, $GIT_DIR/refs/heads, diff --git a/show-branch.c b/show-branch.c index d8808eefce..bff690d988 100644 --- a/show-branch.c +++ b/show-branch.c @@ -1,4 +1,5 @@ #include +#include #include "cache.h" #include "commit.h" #include "refs.h" @@ -332,6 +333,39 @@ static int append_tag_ref(const char *refname, const unsigned char *sha1) return append_ref(refname + 5, sha1); } +static const char *match_ref_pattern = NULL; +static int match_ref_slash = 0; +static int count_slash(const char *s) +{ + int cnt = 0; + while (*s) + if (*s++ == '/') + cnt++; + return cnt; +} + +static int append_matching_ref(const char *refname, const unsigned char *sha1) +{ + /* we want to allow pattern hold/ to show all + * branches under refs/heads/hold/, and v0.99.9? to show + * refs/tags/v0.99.9a and friends. + */ + const char *tail; + int slash = count_slash(refname); + for (tail = refname; *tail && match_ref_slash < slash; ) + if (*tail++ == '/') + slash--; + if (!*tail) + return 0; + if (fnmatch(match_ref_pattern, tail, 0)) + return 0; + if (!strncmp("refs/heads/", refname, 11)) + return append_head_ref(refname, sha1); + if (!strncmp("refs/tags/", refname, 10)) + return append_tag_ref(refname, sha1); + return append_ref(refname, sha1); +} + static void snarf_refs(int head, int tag) { if (head) { @@ -400,6 +434,27 @@ static int show_independent(struct commit **rev, return 0; } +static void append_one_rev(const char *av) +{ + unsigned char revkey[20]; + if (!get_sha1(av, revkey)) { + append_ref(av, revkey); + return; + } + if (strchr(av, '*') || strchr(av, '?')) { + /* glob style match */ + int saved_matches = ref_name_cnt; + match_ref_pattern = av; + match_ref_slash = count_slash(av); + for_each_ref(append_matching_ref); + if (saved_matches == ref_name_cnt && + ref_name_cnt < MAX_REVS) + error("no matching refs with %s", av); + return; + } + die("bad sha1 reference %s", av); +} + int main(int ac, char **av) { struct commit *rev[MAX_REVS], *commit; @@ -458,17 +513,20 @@ int main(int ac, char **av) if (all_heads + all_tags) snarf_refs(all_heads, all_tags); - while (0 < ac) { - unsigned char revkey[20]; - if (get_sha1(*av, revkey)) - die("bad sha1 reference %s", *av); - append_ref(*av, revkey); - ac--; av++; + if (ac) { + while (0 < ac) { + append_one_rev(*av); + ac--; av++; + } } - - /* If still no revs, then add heads */ - if (!ref_name_cnt) + else { + /* If no revs given, then add heads */ snarf_refs(1, 0); + } + if (!ref_name_cnt) { + fprintf(stderr, "No revs to be shown.\n"); + exit(0); + } for (num_rev = 0; ref_name[num_rev]; num_rev++) { unsigned char revkey[20]; -- cgit v1.2.3 From 8bf14d6ef9245f3b81d24cb7725a868f62343277 Mon Sep 17 00:00:00 2001 From: Petr Baudis Date: Sat, 26 Nov 2005 23:12:44 +0100 Subject: Document the --(no-)edit switch of git-revert and git-cherry-pick This switch was not documented properly. I decided not to mention the --no-edit switch in the git-cherry-pick documentation since we always default to no editing. Signed-off-by: Petr Baudis Signed-off-by: Junio C Hamano --- Documentation/git-cherry-pick.txt | 6 +++++- Documentation/git-revert.txt | 11 ++++++++++- git-revert.sh | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 26e0467797..5e0ef5ae0b 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -7,7 +7,7 @@ git-cherry-pick - Apply the change introduced by an existing commit. SYNOPSIS -------- -'git-cherry-pick' [-n] [-r] +'git-cherry-pick' [--edit] [-n] [-r] DESCRIPTION ----------- @@ -20,6 +20,10 @@ OPTIONS :: Commit to cherry-pick. +--edit:: + With this option, `git-cherry-pick` will let you edit the commit + message prior committing. + -r:: Usually the command appends which commit was cherry-picked after the original commit message when diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index feebd81da5..f471037b97 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -7,7 +7,7 @@ git-revert - Revert an existing commit. SYNOPSIS -------- -'git-revert' [-n] +'git-revert' [--edit | --no-edit] [-n] DESCRIPTION ----------- @@ -20,6 +20,15 @@ OPTIONS :: Commit to revert. +--edit:: + With this option, `git-revert` will let you edit the commit + message prior committing the revert. This is the default if + you run the command from a terminal. + +--no-edit:: + With this option, `git-revert` will not start the commit + message editor. + -n:: Usually the command automatically creates a commit with a commit log message stating which commit was reverted. diff --git a/git-revert.sh b/git-revert.sh index c1aebb159c..5cb02b1ec2 100755 --- a/git-revert.sh +++ b/git-revert.sh @@ -19,10 +19,10 @@ esac usage () { case "$me" in cherry-pick) - die "usage git $me [-n] [-r] " + die "usage git $me [--edit] [-n] [-r] " ;; revert) - die "usage git $me [-n] " + die "usage git $me [--edit | --no-edit] [-n] " ;; esac } -- cgit v1.2.3 From f83df6d66e08f1f68b2c1c6aa2ba8b626990df5f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 16:38:40 -0800 Subject: Documentation: rebase does not use cherry-pick anymore. Signed-off-by: Junio C Hamano --- Documentation/git-cherry-pick.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 5e0ef5ae0b..a7a883b83a 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -30,7 +30,7 @@ OPTIONS making a commit. This option, '--replay', causes it to use the original commit message intact. This is useful when you are reordering the patches in your private tree - before publishing, and is used by 'git rebase'. + before publishing. -n:: Usually the command automatically creates a commit with -- cgit v1.2.3 From 18d1e701b70014d37a2715ccce0791114587709e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 21:13:57 -0800 Subject: struct tree: remove unused field "parent" The field is not used anymore, after the recent ls-tree rewrite. Signed-off-by: Junio C Hamano --- tree.c | 1 - tree.h | 1 - 2 files changed, 2 deletions(-) diff --git a/tree.c b/tree.c index 043f032151..e7a7b7190c 100644 --- a/tree.c +++ b/tree.c @@ -200,7 +200,6 @@ int parse_tree_buffer(struct tree *item, void *buffer, unsigned long size) } if (obj) n_refs++; - entry->parent = NULL; /* needs to be filled by the user */ *list_p = entry; list_p = &entry->next; } diff --git a/tree.h b/tree.h index 768e5e9eb8..57a5bf71f2 100644 --- a/tree.h +++ b/tree.h @@ -18,7 +18,6 @@ struct tree_entry_list { struct tree *tree; struct blob *blob; } item; - struct tree_entry_list *parent; }; struct tree { -- cgit v1.2.3 From b270c634b7d3dd197de6d155770fd7b044d76c5c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 21:24:22 -0800 Subject: git.c: remove excess output for debugging when command is too long. When the given command name was too long, we exited with a message with the number of bytes of the final command name inside parentheses, without saying what that number is. It was only meant as a debugging aid while development, so remove it. Signed-off-by: Junio C Hamano --- git.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git.c b/git.c index 0975fc7ac2..ee5048aaaa 100644 --- a/git.c +++ b/git.c @@ -289,7 +289,7 @@ int main(int argc, char **argv, char **envp) len += snprintf(git_command + len, sizeof(git_command) - len, "/git-%s", argv[i]); if (sizeof(git_command) <= len) { - fprintf(stderr, "git: command name given is too long (%d)\n", len); + fprintf(stderr, "git: command name given is too long.\n"); exit(1); } -- cgit v1.2.3 From 1494e03888d084aa1da265f8534d235461b3fc91 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 22:48:43 -0800 Subject: sha1_file.c: make sure packs in an alternate odb is named properly. We somehow ended up registering packs in alternate object directories as "dir/object//pack/pack-*", which confusd the update-server-info code very badly. Also we did not attempt to detect a mistake of listing the object directory itself as one of the alternates. This does not lead to incorrect behaviour, but is simply wasteful, so try to do so when we are trivially able to. Signed-off-by: Junio C Hamano --- sha1_file.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index 82a01887c2..111a71de6b 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -184,8 +184,8 @@ static struct alternate_object_database **alt_odb_tail; * alternate_object_database. The elements on this list come from * non-empty elements from colon separated ALTERNATE_DB_ENVIRONMENT * environment variable, and $GIT_OBJECT_DIRECTORY/info/alternates, - * whose contents is exactly in the same format as that environment - * variable. Its base points at a statically allocated buffer that + * whose contents is similar to that environment variable but can be + * LF separated. Its base points at a statically allocated buffer that * contains "/the/directory/corresponding/to/.git/objects/...", while * its name points just after the slash at the end of ".git/objects/" * in the example above, and has enough space to hold 40-byte hex @@ -197,6 +197,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, { const char *cp, *last; struct alternate_object_database *ent; + const char *objdir = get_object_directory(); int base_len = -1; last = alt; @@ -211,6 +212,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, for ( ; cp < ep && *cp != sep; cp++) ; if (last != cp) { + struct alternate_object_database *alt; /* 43 = 40-byte + 2 '/' + terminating NUL */ int pfxlen = cp - last; int entlen = pfxlen + 43; @@ -223,9 +225,7 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, pfxlen += base_len; } ent = xmalloc(sizeof(*ent) + entlen); - *alt_odb_tail = ent; - alt_odb_tail = &(ent->next); - ent->next = NULL; + if (*last != '/' && relative_base) { memcpy(ent->base, relative_base, base_len - 1); ent->base[base_len - 1] = '/'; @@ -237,6 +237,22 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep, ent->name = ent->base + pfxlen + 1; ent->base[pfxlen] = ent->base[pfxlen + 3] = '/'; ent->base[entlen-1] = 0; + + /* Prevent the common mistake of listing the same + * thing twice, or object directory itself. + */ + for (alt = alt_odb_list; alt; alt = alt->next) + if (!memcmp(ent->base, alt->base, pfxlen)) + goto bad; + if (!memcmp(ent->base, objdir, pfxlen)) { + bad: + free(ent); + } + else { + *alt_odb_tail = ent; + alt_odb_tail = &(ent->next); + ent->next = NULL; + } } while (cp < ep && *cp == sep) cp++; @@ -531,8 +547,9 @@ void prepare_packed_git(void) prepare_packed_git_one(get_object_directory(), 1); prepare_alt_odb(); for (alt = alt_odb_list; alt; alt = alt->next) { - alt->name[0] = 0; + alt->name[-1] = 0; prepare_packed_git_one(alt->base, 0); + alt->name[-1] = '/'; } run_once = 1; } -- cgit v1.2.3 From 6f42f89c1f7030d1101f08bf56d06cc2b6828b83 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 22:52:19 -0800 Subject: server-info.c: drop unused D lines. We tried to compute pack interdependency information in $GIT_DIR/objects/info/packs, hoping that dumb transports would make use of it when choosing from multiple choice, but that has never materialized, so stop computing D lines for now. Signed-off-by: Junio C Hamano --- server-info.c | 120 +++++----------------------------------------------------- 1 file changed, 10 insertions(+), 110 deletions(-) diff --git a/server-info.c b/server-info.c index e4006f0b5b..2cd1432249 100644 --- a/server-info.c +++ b/server-info.c @@ -51,7 +51,6 @@ static struct pack_info { int nr_alloc; int nr_heads; unsigned char (*head)[20]; - char dep[0]; /* more */ } **info; static int num_pack; static const char *objdir; @@ -123,49 +122,12 @@ static int parse_pack_def(const char *line, int old_cnt) return 0; } else { - /* The file describes a pack that is no longer here; - * dependencies between packs needs to be recalculated. - */ + /* The file describes a pack that is no longer here */ return 1; } } -/* Returns non-zero when we detect that the info in the - * old file is useless. - */ -static int parse_depend_def(char *line) -{ - unsigned long num; - char *cp, *ep; - struct pack_info *this, *that; - - cp = line + 2; - num = strtoul(cp, &ep, 10); - if (ep == cp) - return error("invalid input %s", line); - this = find_pack_by_old_num(num); - if (!this) - return 0; - while (ep && *(cp = ep)) { - num = strtoul(cp, &ep, 10); - if (ep == cp) - break; - that = find_pack_by_old_num(num); - if (!that) - /* The pack this one depends on does not - * exist; this should not happen because - * we write out the list of packs first and - * then dependency information, but it means - * the file is useless anyway. - */ - return 1; - this->dep[that->new_num] = 1; - } - return 0; -} - -/* Returns non-zero when we detect that the info in the - * old file is useless. +/* Returns non-zero when we detect that the info in the old file is useless. */ static int parse_head_def(char *line) { @@ -212,9 +174,8 @@ static int read_pack_info_file(const char *infofile) if (parse_pack_def(line, old_cnt++)) goto out_stale; break; - case 'D': /* D ix dep-ix1 dep-ix2... */ - if (parse_depend_def(line)) - goto out_stale; + case 'D': /* we used to emit D but that was misguided. */ + goto out_stale; break; case 'T': /* T ix sha1 type */ if (parse_head_def(line)) @@ -286,7 +247,6 @@ static void init_pack_info(const char *infofile, int force) struct packed_git *p; int stale; int i = 0; - char *dep_temp; objdir = get_object_directory(); objdirlen = strlen(objdir); @@ -307,7 +267,7 @@ static void init_pack_info(const char *infofile, int force) if (strncmp(p->pack_name, objdir, objdirlen) || p->pack_name[objdirlen] != '/') continue; - info[i] = xcalloc(1, sizeof(struct pack_info) + num_pack); + info[i] = xcalloc(1, sizeof(struct pack_info)); info[i]->p = p; info[i]->old_num = -1; i++; @@ -321,41 +281,16 @@ static void init_pack_info(const char *infofile, int force) for (i = 0; i < num_pack; i++) { if (stale) { info[i]->old_num = -1; - memset(info[i]->dep, 0, num_pack); info[i]->nr_heads = 0; } if (info[i]->old_num < 0) info[i]->latest = get_latest_commit_date(info[i]->p); } + /* renumber them */ qsort(info, num_pack, sizeof(info[0]), compare_info); for (i = 0; i < num_pack; i++) info[i]->new_num = i; - - /* we need to fix up the dependency information - * for the old ones. - */ - dep_temp = NULL; - for (i = 0; i < num_pack; i++) { - int old; - - if (info[i]->old_num < 0) - continue; - if (! dep_temp) - dep_temp = xmalloc(num_pack); - memset(dep_temp, 0, num_pack); - for (old = 0; old < num_pack; old++) { - struct pack_info *base; - if (!info[i]->dep[old]) - continue; - base = find_pack_by_old_num(old); - if (!base) - die("internal error renumbering"); - dep_temp[base->new_num] = 1; - } - memcpy(info[i]->dep, dep_temp, num_pack); - } - free(dep_temp); } static void write_pack_info_file(FILE *fp) @@ -363,17 +298,6 @@ static void write_pack_info_file(FILE *fp) int i, j; for (i = 0; i < num_pack; i++) fprintf(fp, "P %s\n", info[i]->p->pack_name + objdirlen + 6); - - for (i = 0; i < num_pack; i++) { - fprintf(fp, "D %1d", i); - for (j = 0; j < num_pack; j++) { - if ((i == j) || !(info[i]->dep[j])) - continue; - fprintf(fp, " %1d", j); - } - fputc('\n', fp); - } - for (i = 0; i < num_pack; i++) { struct pack_info *this = info[i]; for (j = 0; j < this->nr_heads; j++) { @@ -386,37 +310,18 @@ static void write_pack_info_file(FILE *fp) } #define REFERENCED 01 -#define INTERNAL 02 #define EMITTED 04 static void show(struct object *o, int pack_ix) { /* * We are interested in objects that are not referenced, - * and objects that are referenced but not internal. */ if (o->flags & EMITTED) return; if (!(o->flags & REFERENCED)) add_head_def(info[pack_ix], o->sha1); - else if ((o->flags & REFERENCED) && !(o->flags & INTERNAL)) { - int i; - - /* Which pack contains this object? That is what - * pack_ix can depend on. We earlier sorted info - * array from youngest to oldest, so try newer packs - * first to favor them here. - */ - for (i = num_pack - 1; 0 <= i; i--) { - struct packed_git *p = info[i]->p; - struct pack_entry ent; - if (find_pack_entry_one(o->sha1, &ent, p)) { - info[pack_ix]->dep[i] = 1; - break; - } - } - } o->flags |= EMITTED; } @@ -445,7 +350,7 @@ static void find_pack_info_one(int pack_ix) o->flags = 0; } - /* Mark all the internal ones */ + /* Mark all the referenced ones */ for (i = 0; i < num; i++) { if (nth_packed_object_sha1(p, i, sha1)) die("corrupt pack file %s?", p->pack_name); @@ -457,7 +362,6 @@ static void find_pack_info_one(int pack_ix) for (j = 0; j < refs->count; j++) refs->ref[j]->flags |= REFERENCED; } - o->flags |= INTERNAL; } for (i = 0; i < num; i++) { @@ -465,14 +369,7 @@ static void find_pack_info_one(int pack_ix) die("corrupt pack file %s?", p->pack_name); if ((o = lookup_object(sha1)) == NULL) die("cannot find %s", sha1_to_hex(sha1)); - show(o, pack_ix); - if (o->refs) { - struct object_refs *refs = o->refs; - int j; - for (j = 0; j < refs->count; j++) - show(refs->ref[j], pack_ix); - } } } @@ -530,5 +427,8 @@ int update_server_info(int force) errs = errs | update_info_refs(force); errs = errs | update_info_packs(force); + /* remove leftover rev-cache file if there is any */ + unlink(git_path("info/rev-cache")); + return errs; } -- cgit v1.2.3 From d5eac49868eba3b13d4816b82e99e86ec5ac9eb8 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 23:02:54 -0800 Subject: server-info: stop sorting packs by latest date. This does not seem to buy us much, for the same reason as the previous change. Dumb clients are still too dumb. Signed-off-by: Junio C Hamano --- server-info.c | 39 +++------------------------------------ 1 file changed, 3 insertions(+), 36 deletions(-) diff --git a/server-info.c b/server-info.c index 2cd1432249..9dd19bd536 100644 --- a/server-info.c +++ b/server-info.c @@ -44,7 +44,6 @@ static int update_info_refs(int force) /* packs */ static struct pack_info { - unsigned long latest; struct packed_git *p; int old_num; int new_num; @@ -193,32 +192,6 @@ static int read_pack_info_file(const char *infofile) return 1; } -/* We sort the packs according to the date of the latest commit. That - * in turn indicates how young the pack is, and in general we would - * want to depend on younger packs. - */ -static unsigned long get_latest_commit_date(struct packed_git *p) -{ - unsigned char sha1[20]; - struct object *o; - int num = num_packed_objects(p); - int i; - unsigned long latest = 0; - - for (i = 0; i < num; i++) { - if (nth_packed_object_sha1(p, i, sha1)) - die("corrupt pack file %s?", p->pack_name); - if ((o = parse_object_cheap(sha1)) == NULL) - die("cannot parse %s", sha1_to_hex(sha1)); - if (o->type == commit_type) { - struct commit *commit = (struct commit *)o; - if (latest < commit->date) - latest = commit->date; - } - } - return latest; -} - static int compare_info(const void *a_, const void *b_) { struct pack_info * const* a = a_; @@ -234,12 +207,8 @@ static int compare_info(const void *a_, const void *b_) /* The other way around. */ return 1; - if ((*a)->latest < (*b)->latest) - return -1; - else if ((*a)->latest == (*b)->latest) - return 0; - else - return 1; + /* then it does not matter but at least keep the comparison stable */ + return (*a)->p - (*b)->p; } static void init_pack_info(const char *infofile, int force) @@ -283,8 +252,6 @@ static void init_pack_info(const char *infofile, int force) info[i]->old_num = -1; info[i]->nr_heads = 0; } - if (info[i]->old_num < 0) - info[i]->latest = get_latest_commit_date(info[i]->p); } /* renumber them */ @@ -339,7 +306,7 @@ static void find_pack_info_one(int pack_ix) for (i = 0; i < num; i++) { if (nth_packed_object_sha1(p, i, sha1)) die("corrupt pack file %s?", p->pack_name); - if ((o = lookup_object(sha1)) == NULL) + if ((o = parse_object_cheap(sha1)) == NULL) die("cannot parse %s", sha1_to_hex(sha1)); if (o->refs) { struct object_refs *refs = o->refs; -- cgit v1.2.3 From 3e15c67c90f8eaa655165cf642d0553919a06464 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 4 Dec 2005 23:12:36 -0800 Subject: server-info: throw away T computation as well. Again, dumb transport clients are too dumb to make use of the top objects information to make a choice among multiple packs, so computing these lines are useless for now. We could resurrect them if needed later. Also dumb transport clients presumably can do their own approximation by downloading idx files to see how relevant each pack is for their fetch. Signed-off-by: Junio C Hamano --- server-info.c | 133 ++-------------------------------------------------------- 1 file changed, 3 insertions(+), 130 deletions(-) diff --git a/server-info.c b/server-info.c index 9dd19bd536..cb67c1f2de 100644 --- a/server-info.c +++ b/server-info.c @@ -100,16 +100,6 @@ static struct pack_info *find_pack_by_old_num(int old_num) return NULL; } -static int add_head_def(struct pack_info *this, unsigned char *sha1) -{ - if (this->nr_alloc <= this->nr_heads) { - this->nr_alloc = alloc_nr(this->nr_alloc); - this->head = xrealloc(this->head, this->nr_alloc * 20); - } - memcpy(this->head[this->nr_heads++], sha1, 20); - return 0; -} - /* Returns non-zero when we detect that the info in the * old file is useless. */ @@ -126,30 +116,6 @@ static int parse_pack_def(const char *line, int old_cnt) } } -/* Returns non-zero when we detect that the info in the old file is useless. - */ -static int parse_head_def(char *line) -{ - unsigned char sha1[20]; - unsigned long num; - char *cp, *ep; - struct pack_info *this; - struct object *o; - - cp = line + 2; - num = strtoul(cp, &ep, 10); - if (ep == cp || *ep++ != ' ') - return error("invalid input ix %s", line); - this = find_pack_by_old_num(num); - if (!this) - return 1; /* You know the drill. */ - if (get_sha1_hex(ep, sha1) || ep[40] != ' ') - return error("invalid input sha1 %s (%s)", line, ep); - if ((o = parse_object_cheap(sha1)) == NULL) - return error("no such object: %s", line); - return add_head_def(this, sha1); -} - /* Returns non-zero when we detect that the info in the * old file is useless. */ @@ -176,9 +142,8 @@ static int read_pack_info_file(const char *infofile) case 'D': /* we used to emit D but that was misguided. */ goto out_stale; break; - case 'T': /* T ix sha1 type */ - if (parse_head_def(line)) - goto out_stale; + case 'T': /* we used to emit T but nobody uses it. */ + goto out_stale; break; default: error("unrecognized: %s", line); @@ -262,100 +227,9 @@ static void init_pack_info(const char *infofile, int force) static void write_pack_info_file(FILE *fp) { - int i, j; + int i; for (i = 0; i < num_pack; i++) fprintf(fp, "P %s\n", info[i]->p->pack_name + objdirlen + 6); - for (i = 0; i < num_pack; i++) { - struct pack_info *this = info[i]; - for (j = 0; j < this->nr_heads; j++) { - struct object *o = lookup_object(this->head[j]); - fprintf(fp, "T %1d %s %s\n", - i, sha1_to_hex(this->head[j]), o->type); - } - } - -} - -#define REFERENCED 01 -#define EMITTED 04 - -static void show(struct object *o, int pack_ix) -{ - /* - * We are interested in objects that are not referenced, - */ - if (o->flags & EMITTED) - return; - - if (!(o->flags & REFERENCED)) - add_head_def(info[pack_ix], o->sha1); - o->flags |= EMITTED; -} - -static void find_pack_info_one(int pack_ix) -{ - unsigned char sha1[20]; - struct object *o; - int i; - struct packed_git *p = info[pack_ix]->p; - int num = num_packed_objects(p); - - /* Scan objects, clear flags from all the edge ones and - * internal ones, possibly marked in the previous round. - */ - for (i = 0; i < num; i++) { - if (nth_packed_object_sha1(p, i, sha1)) - die("corrupt pack file %s?", p->pack_name); - if ((o = parse_object_cheap(sha1)) == NULL) - die("cannot parse %s", sha1_to_hex(sha1)); - if (o->refs) { - struct object_refs *refs = o->refs; - int j; - for (j = 0; j < refs->count; j++) - refs->ref[j]->flags = 0; - } - o->flags = 0; - } - - /* Mark all the referenced ones */ - for (i = 0; i < num; i++) { - if (nth_packed_object_sha1(p, i, sha1)) - die("corrupt pack file %s?", p->pack_name); - if ((o = lookup_object(sha1)) == NULL) - die("cannot find %s", sha1_to_hex(sha1)); - if (o->refs) { - struct object_refs *refs = o->refs; - int j; - for (j = 0; j < refs->count; j++) - refs->ref[j]->flags |= REFERENCED; - } - } - - for (i = 0; i < num; i++) { - if (nth_packed_object_sha1(p, i, sha1)) - die("corrupt pack file %s?", p->pack_name); - if ((o = lookup_object(sha1)) == NULL) - die("cannot find %s", sha1_to_hex(sha1)); - show(o, pack_ix); - } - -} - -static void find_pack_info(void) -{ - int i; - for (i = 0; i < num_pack; i++) { - /* The packed objects are cast in stone, and a head - * in a pack will stay as head, so is the set of missing - * objects. If the repo has been reorganized and we - * are missing some packs available back then, we have - * already discarded the info read from the file, so - * we will find (old_num < 0) in that case. - */ - if (0 <= info[i]->old_num) - continue; - find_pack_info_one(i); - } } static int update_info_packs(int force) @@ -370,7 +244,6 @@ static int update_info_packs(int force) strcpy(name + namelen, "+"); init_pack_info(infofile, force); - find_pack_info(); safe_create_leading_directories(name); fp = fopen(name, "w"); -- cgit v1.2.3 From 556cb4e583ada79b7c2e632a548dca90a98c1b29 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 00:15:24 -0800 Subject: Documentation: talk about pathspec in bisect. Also work-around asciidoc manpage trouble that does not seem to allow more than one line in the SYNOPSIS section. Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 66 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 8a399703dc..ac4b4965a9 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -8,16 +8,21 @@ git-bisect - Find the change that introduced a bug SYNOPSIS -------- - 'git bisect' start - 'git bisect' bad - 'git bisect' good - 'git bisect' reset [] - 'git bisect' visualize - 'git bisect' replay - 'git bisect' log +'git bisect' DESCRIPTION ----------- +The command takes various subcommands, and different options +depending on the subcommand: + + git bisect start [...] + git bisect bad + git bisect good + git bisect reset [] + git bisect visualize + git bisect replay + git bisect log + This command uses 'git-rev-list --bisect' option to help drive the binary search process to find which change introduced a bug, given an old "good" commit object name and a later "bad" commit @@ -26,10 +31,10 @@ object name. The way you use it is: ------------------------------------------------ -git bisect start -git bisect bad # Current version is bad -git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version - # tested that was good +$ git bisect start +$ git bisect bad # Current version is bad +$ git bisect good v2.6.13-rc2 # v2.6.13-rc2 was the last version + # tested that was good ------------------------------------------------ When you give at least one bad and one good versions, it will @@ -43,7 +48,7 @@ and check out the state in the middle. Now, compile that kernel, and boot it. Now, let's say that this booted kernel works fine, then just do ------------------------------------------------ -git bisect good # this one is good +$ git bisect good # this one is good ------------------------------------------------ which will now say @@ -62,7 +67,7 @@ kernel rev in "refs/bisect/bad". Oh, and then after you want to reset to the original head, do a ------------------------------------------------ -git bisect reset +$ git bisect reset ------------------------------------------------ to get back to the master branch, instead of being in one of the bisection @@ -72,7 +77,9 @@ not using some old bisection branch). During the bisection process, you can say - git bisect visualize +------------ +$ git bisect visualize +------------ to see the currently remaining suspects in `gitk`. @@ -80,11 +87,40 @@ The good/bad input is logged, and `git bisect log` shows what you have done so far. You can truncate its output somewhere and save it in a file, and run - git bisect replay that-file +------------ +$ git bisect replay that-file +------------ if you find later you made a mistake telling good/bad about a revision. +If in a middle of bisect session, you know what the bisect +suggested to try next is not a good one to test (e.g. the change +the commit introduces is known not to work in your environment +and you know it does not have anything to do with the bug you +are chasing), you may want to find a near-by commit and try that +instead. It goes something like this: + +------------ +$ git bisect good/bad # previous round was good/bad. +Bisecting: 337 revisions left to test after this +$ git bisect visualize # oops, that is uninteresting. +$ git reset --hard HEAD~3 # try 3 revs before what + # was suggested +------------ + +Then compile and test the one you chose to try. After that, +tell bisect what the result was as usual. + +You can further cut down the number of trials if you know what +part of the tree is involved in the problem you are tracking +down, by giving paths parameters when you say `bisect start`, +like this: + +------------ +$ git bisect start arch/i386 include/asm-i386 +------------ + Author ------ -- cgit v1.2.3 From 63d34b0b13b3527eb63dce5e37098e200f6a0717 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 00:15:44 -0800 Subject: Documentation: git-mv manpage workaround. Work-around asciidoc manpage trouble that does not seem to allow more than one line in the SYNOPSIS section. Signed-off-by: Junio C Hamano --- Documentation/git-mv.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/git-mv.txt b/Documentation/git-mv.txt index 3013b8d0c2..d242b39654 100644 --- a/Documentation/git-mv.txt +++ b/Documentation/git-mv.txt @@ -8,12 +8,15 @@ git-mv - Script used to move or rename a file, directory or symlink. SYNOPSIS -------- - 'git-mv' [-f] [-n] - 'git-mv' [-f] [-n] [-k] ... +'git-mv' ... ... DESCRIPTION ----------- This script is used to move or rename a file, directory or symlink. + + git-mv [-f] [-n] + git-mv [-f] [-n] [-k] ... + In the first form, it renames , which must exist and be either a file, symlink or directory, to . In the second form, the last argument has to be an existing -- cgit v1.2.3 From dfa2f22f942ffc96105e667024b516e6f4fa07d1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 00:22:01 -0800 Subject: Documentation: git-diff asciidoc table workaround. The table facility was nice in rendering HTML but was disastrous for man page. Reword the text and do not use table for now. Signed-off-by: Junio C Hamano --- Documentation/git-diff.txt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt index cadaf59455..cf7527f5e9 100644 --- a/Documentation/git-diff.txt +++ b/Documentation/git-diff.txt @@ -17,14 +17,16 @@ ent and the index file, or the index file and the working tree. The combination of what is compared with what is determined by the number of ents given to the command. -`----------------`--------`-----------------------------`------------------ -Number of ents Options What's Compared Underlying command ---------------------------------------------------------------------------- -0 - index file and working tree git-diff-files -1 --cached ent and index file git-diff-index -1 - ent and working tree git-diff-index -2 - two ents git-diff-tree ---------------------------------------------------------------------------- +* When no is given, the working tree and the index + file is compared, using `git-diff-files`. + +* When one is given, the working tree and the named + tree is compared, using `git-diff-index`. The option + `--cached` can be given to compare the index file and + the named tree. + +* When two s are given, these two trees are compared + using `git-diff-tree`. OPTIONS ------- -- cgit v1.2.3 From eb0362a467cc2cb5313bb859d78ea2d152b4a4ff Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 00:32:01 -0800 Subject: Documentation: push/receive hook references. Mention documentation pages that talk about update and post-update hooks from git-push, because a frequently asked question is "I want X to happen when I push" and people would not know to look at git-receive-pack documentation until they understand that is what runs on the other end. Signed-off-by: Junio C Hamano --- Documentation/git-push.txt | 5 +++++ Documentation/git-receive-pack.txt | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt index f45ac5ee49..2254bac16e 100644 --- a/Documentation/git-push.txt +++ b/Documentation/git-push.txt @@ -16,6 +16,10 @@ DESCRIPTION Updates remote refs using local refs, while sending objects necessary to complete the given refs. +You can make "interesting" things to happen on the repository +every time you push into it, by setting up 'hooks' there. See +documentation for gitlink:git-receive-pack[1]. + OPTIONS ------- @@ -31,6 +35,7 @@ include::pull-fetch-param.txt[] This flag disables the check. What this means is that the local repository can lose commits; use it with care. + Author ------ Written by Junio C Hamano diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt index 8afde14373..60debca487 100644 --- a/Documentation/git-receive-pack.txt +++ b/Documentation/git-receive-pack.txt @@ -71,6 +71,10 @@ packed and is served via a dumb transport. #!/bin/sh exec git-update-server-info +There are other real-world examples of using update and +post-update hooks found in the Documentation/howto directory. + + OPTIONS ------- :: -- cgit v1.2.3 From dc5f9239f7cc577b7d503017583dcc26ad5991f0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 00:57:48 -0800 Subject: Documentation: shared repository management in tutorial. The branch policy script I outlined was improved and polished by Carl and posted on the list twice since then. It is a shame not to pick it up, so replace the original outline in howto/update-hook-example.txt with the latest from Carl. Also talk about setting up git-shell to allow git-push/git-fetch only SSH access to a shared repository host in the tutorial. Signed-off-by: Junio C Hamano --- Documentation/howto/update-hook-example.txt | 205 ++++++++++++++++++---------- Documentation/tutorial.txt | 35 +++++ 2 files changed, 171 insertions(+), 69 deletions(-) diff --git a/Documentation/howto/update-hook-example.txt b/Documentation/howto/update-hook-example.txt index dacaf17c2e..3a33696f00 100644 --- a/Documentation/howto/update-hook-example.txt +++ b/Documentation/howto/update-hook-example.txt @@ -1,4 +1,4 @@ -From: Junio C Hamano +From: Junio C Hamano and Carl Baldwin Subject: control access to branches. Date: Thu, 17 Nov 2005 23:55:32 -0800 Message-ID: <7vfypumlu3.fsf@assigned-by-dhcp.cox.net> @@ -26,63 +26,137 @@ section of the documentation: So if your policy is (1) always require fast-forward push (i.e. never allow "git-push repo +branch:branch"), (2) you have a list of users allowed to update each branch, and (3) you -do not let tags to be overwritten, then: - - #!/bin/sh - # This is a sample hooks/update script, written by JC - # in his e-mail buffer, so naturally it is not tested - # but hopefully would convey the idea. - - umask 002 - case "$1" in - refs/tags/*) - # No overwriting an existing tag - if test -f "$GIT_DIR/$1" - then - exit 1 - fi - ;; - refs/heads/*) - # No rebasing or rewinding - if expr "$2" : '0*$' >/dev/null - then - # creating a new branch - ; - else - # updating -- make sure it is a fast forward - mb=`git-merge-base "$2" "$3"` - case "$mb,$2" in - "$2,$mb") - ;; # fast forward -- happy - *) - exit 1 ;; # unhappy - esac - fi - ;; - *) - # No funny refs allowed - exit 1 - ;; - esac - - # Is the user allowed to update it? - me=`id -u -n` ;# e.g. "junio" - while read head_pattern users - do - if expr "$1" : "$head_pattern" >/dev/null - then - case " $users " in - *" $me "*) - exit 0 ;; # happy - ' * ') - exit 0 ;; # anybody - esac - fi - done - exit 1 - -For the sake of simplicity, I assumed that you keep something -like this in $GIT_DIR/info/allowed-pushers file: +do not let tags to be overwritten, then you can use something +like this as your hooks/update script. + +[jc: editorial note. This is a much improved version by Carl +since I posted the original outline] + +-- >8 -- beginning of script -- >8 -- + +#!/bin/bash + +umask 002 + +# If you are having trouble with this access control hook script +# you can try setting this to true. It will tell you exactly +# why a user is being allowed/denied access. + +verbose=false + +# Default shell globbing messes things up downstream +GLOBIGNORE=* + +function grant { + $verbose && echo >&2 "-Grant- $1" + echo grant + exit 0 +} + +function deny { + $verbose && echo >&2 "-Deny- $1" + echo deny + exit 1 +} + +function info { + $verbose && echo >&2 "-Info- $1" +} + +# Implement generic branch and tag policies. +# - Tags should not be updated once created. +# - Branches should only be fast-forwarded. +case "$1" in + refs/tags/*) + [ -f "$GIT_DIR/$1" ] && + deny >/dev/null "You can't overwrite an existing tag" + ;; + refs/heads/*) + # No rebasing or rewinding + if expr "$2" : '0*$' >/dev/null; then + info "The branch '$1' is new..." + else + # updating -- make sure it is a fast forward + mb=$(git-merge-base "$2" "$3") + case "$mb,$2" in + "$2,$mb") info "Update is fast-forward" ;; + *) deny >/dev/null "This is not a fast-forward update." ;; + esac + fi + ;; + *) + deny >/dev/null \ + "Branch is not under refs/heads or refs/tags. What are you trying to do?" + ;; +esac + +# Implement per-branch controls based on username +allowed_users_file=$GIT_DIR/info/allowed-users +username=$(id -u -n) +info "The user is: '$username'" + +if [ -f "$allowed_users_file" ]; then + rc=$(cat $allowed_users_file | grep -v '^#' | grep -v '^$' | + while read head_pattern user_patterns; do + matchlen=$(expr "$1" : "$head_pattern") + if [ "$matchlen" == "${#1}" ]; then + info "Found matching head pattern: '$head_pattern'" + for user_pattern in $user_patterns; do + info "Checking user: '$username' against pattern: '$user_pattern'" + matchlen=$(expr "$username" : "$user_pattern") + if [ "$matchlen" == "${#username}" ]; then + grant "Allowing user: '$username' with pattern: '$user_pattern'" + fi + done + deny "The user is not in the access list for this branch" + fi + done + ) + case "$rc" in + grant) grant >/dev/null "Granting access based on $allowed_users_file" ;; + deny) deny >/dev/null "Denying access based on $allowed_users_file" ;; + *) ;; + esac +fi + +allowed_groups_file=$GIT_DIR/info/allowed-groups +groups=$(id -G -n) +info "The user belongs to the following groups:" +info "'$groups'" + +if [ -f "$allowed_groups_file" ]; then + rc=$(cat $allowed_groups_file | grep -v '^#' | grep -v '^$' | + while read head_pattern group_patterns; do + matchlen=$(expr "$1" : "$head_pattern") + if [ "$matchlen" == "${#1}" ]; then + info "Found matching head pattern: '$head_pattern'" + for group_pattern in $group_patterns; do + for groupname in $groups; do + info "Checking group: '$groupname' against pattern: '$group_pattern'" + matchlen=$(expr "$groupname" : "$group_pattern") + if [ "$matchlen" == "${#groupname}" ]; then + grant "Allowing group: '$groupname' with pattern: '$group_pattern'" + fi + done + done + deny "None of the user's groups are in the access list for this branch" + fi + done + ) + case "$rc" in + grant) grant >/dev/null "Granting access based on $allowed_groups_file" ;; + deny) deny >/dev/null "Denying access based on $allowed_groups_file" ;; + *) ;; + esac +fi + +deny >/dev/null "There are no more rules to check. Denying access" + +-- >8 -- end of script -- >8 -- + +This uses two files, $GIT_DIR/info/allowed-users and +allowed-groups, to describe which heads can be pushed into by +whom. The format of each file would look like this: refs/heads/master junio refs/heads/cogito$ pasky @@ -91,15 +165,8 @@ like this in $GIT_DIR/info/allowed-pushers file: refs/tags/v[0-9]* junio With this, Linus can push or create "bw/penguin" or "bw/zebra" -or "bw/panda" branches, Pasky can do only "cogito", and I can do -master branch and make versioned tags. And anybody can do -tmp/blah branches. This assumes all the users are in a single -group that can write into $GIT_DIR/ and underneath. - - - - - - - +or "bw/panda" branches, Pasky can do only "cogito", and JC can +do master branch and make versioned tags. And anybody can do +tmp/blah branches. +------------ diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index cf7ba76ddf..db0bf3e527 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1636,6 +1636,41 @@ fast forward. You need to pull and merge those other changes back before you push your work when it happens. +Advanced Shared Repository Management +------------------------------------- + +Being able to push into a shared repository means being able to +write into it. If your developers are coming over the network, +this means you, as the repository administrator, need to give +each of them an SSH access to the shared repository machine. + +In some cases, though, you may not want to give a normal shell +account to them, but want to restrict them to be able to only +do `git push` into the repository and nothing else. + +You can achieve this by setting the login shell of your +developers on the shared repository host to `git-shell` program. + +[NOTE] +Most likely you would also need to list `git-shell` program in +`/etc/shells` file. + +This restricts the set of commands that can be run from incoming +SSH connection for these users to only `receive-pack` and +`upload-pack`, so the only thing they can do are `git fetch` and +`git push`. + +You still need to create UNIX user accounts for each developer, +and put them in the same group. Make sure that the repository +shared among these developers is writable by that group. + +You can implement finer grained branch policies using update +hooks. There is a document ("control access to branches") in +Documentation/howto by Carl Baldwin and JC outlining how to (1) +limit access to branch per user, (2) forbid overwriting existing +tags. + + Bundling your work together --------------------------- -- cgit v1.2.3 From f13d7db4af3bbf611990d63643b34c4e546b127c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 10:39:17 -0800 Subject: server-info.c: use pack_local like everybody else. Signed-off-by: Junio C Hamano --- server-info.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/server-info.c b/server-info.c index cb67c1f2de..7b214c8138 100644 --- a/server-info.c +++ b/server-info.c @@ -190,16 +190,14 @@ static void init_pack_info(const char *infofile, int force) /* we ignore things on alternate path since they are * not available to the pullers in general. */ - if (strncmp(p->pack_name, objdir, objdirlen) || - strncmp(p->pack_name + objdirlen, "/pack/", 6)) + if (!p->pack_local) continue; i++; } num_pack = i; info = xcalloc(num_pack, sizeof(struct pack_info *)); for (i = 0, p = packed_git; p; p = p->next) { - if (strncmp(p->pack_name, objdir, objdirlen) || - p->pack_name[objdirlen] != '/') + if (!p->pack_local) continue; info[i] = xcalloc(1, sizeof(struct pack_info)); info[i]->p = p; -- cgit v1.2.3 From 9cebe90bc55c76638f5cb8132d9fbd2769e05e54 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 11:12:01 -0800 Subject: server-info.c: and two functions are not used anymore. Signed-off-by: Junio C Hamano --- server-info.c | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/server-info.c b/server-info.c index 7b214c8138..7d7bcb2188 100644 --- a/server-info.c +++ b/server-info.c @@ -55,30 +55,6 @@ static int num_pack; static const char *objdir; static int objdirlen; -static struct object *parse_object_cheap(const unsigned char *sha1) -{ - struct object *o; - - if ((o = parse_object(sha1)) == NULL) - return NULL; - if (o->type == commit_type) { - struct commit *commit = (struct commit *)o; - free(commit->buffer); - commit->buffer = NULL; - } else if (o->type == tree_type) { - struct tree *tree = (struct tree *)o; - struct tree_entry_list *e, *n; - for (e = tree->entries; e; e = n) { - free(e->name); - e->name = NULL; - n = e->next; - free(e); - } - tree->entries = NULL; - } - return o; -} - static struct pack_info *find_pack_by_name(const char *name) { int i; @@ -91,15 +67,6 @@ static struct pack_info *find_pack_by_name(const char *name) return NULL; } -static struct pack_info *find_pack_by_old_num(int old_num) -{ - int i; - for (i = 0; i < num_pack; i++) - if (info[i]->old_num == old_num) - return info[i]; - return NULL; -} - /* Returns non-zero when we detect that the info in the * old file is useless. */ -- cgit v1.2.3 From 53e7181cd9927a8a194f4770c597744d96a113a2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 25 Nov 2005 14:22:27 -0800 Subject: config.c: remove unnecessary header in minimum configuration file. It is just silly to start the file called "config" with a comment that says "This is the config file." Signed-off-by: Junio C Hamano --- config.c | 8 -------- t/t1300-repo-config.sh | 20 -------------------- 2 files changed, 28 deletions(-) diff --git a/config.c b/config.c index 34584f62b4..5b5a9a2e4c 100644 --- a/config.c +++ b/config.c @@ -458,12 +458,6 @@ int git_config_set_multivar(const char* key, const char* value, * If .git/config does not exist yet, write a minimal version. */ if (stat(config_filename, &st)) { - static const char contents[] = - "#\n" - "# This is the config file\n" - "#\n" - "\n"; - free(store.key); /* if nothing to unset, error out */ @@ -474,8 +468,6 @@ int git_config_set_multivar(const char* key, const char* value, } store.key = (char*)key; - - write(fd, contents, sizeof(contents)-1); store_write_section(fd, key); store_write_pair(fd, key, value); } else{ diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 5e994ff009..207dd3de64 100644 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -12,10 +12,6 @@ test -f .git/config && rm .git/config git-repo-config core.penguin "little blue" cat > expect << EOF -# -# This is the config file -# - [core] penguin = little blue EOF @@ -25,10 +21,6 @@ test_expect_success 'initial' 'cmp .git/config expect' git-repo-config Core.Movie BadPhysics cat > expect << EOF -# -# This is the config file -# - [core] penguin = little blue Movie = BadPhysics @@ -39,10 +31,6 @@ test_expect_success 'mixed case' 'cmp .git/config expect' git-repo-config Cores.WhatEver Second cat > expect << EOF -# -# This is the config file -# - [core] penguin = little blue Movie = BadPhysics @@ -55,10 +43,6 @@ test_expect_success 'similar section' 'cmp .git/config expect' git-repo-config CORE.UPPERCASE true cat > expect << EOF -# -# This is the config file -# - [core] penguin = little blue Movie = BadPhysics @@ -76,10 +60,6 @@ test_expect_success 'replace with non-match (actually matching)' \ 'git-repo-config core.penguin "very blue" !kingpin' cat > expect << EOF -# -# This is the config file -# - [core] penguin = very blue Movie = BadPhysics -- cgit v1.2.3 From cd8c4589473d2a6669cf882ebcd708a2d81e9168 Mon Sep 17 00:00:00 2001 From: Jason Riedy Date: Mon, 5 Dec 2005 10:38:30 -0800 Subject: [PATCH] Document config.mak in INSTALL. The existing config.mak should satisfy almost everyone... You can change the prefix and other vars catch the new setting anyways. I had forgotten that ?= acts as = (lazy value binding) and as not := (immediate value binding). Signed-off-by: E. Jason Riedy Signed-off-by: Junio C Hamano --- INSTALL | 3 +++ 1 file changed, 3 insertions(+) diff --git a/INSTALL b/INSTALL index 63ccf62ae9..916ddd400b 100644 --- a/INSTALL +++ b/INSTALL @@ -87,3 +87,6 @@ Issues of note: have all the libraries/tools needed, or you may have necessary libraries at unusual locations. Please look at the top of the Makefile to see what can be adjusted for your needs. + You can place local settings in config.mak and the Makefile + will include them. Note that config.mak is not distributed; + the name is reserved for local settings. -- cgit v1.2.3 From 4dd5d0d9eb8429a217ec43682e2e2eef8a8cbf6d Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Tue, 6 Dec 2005 09:46:23 +1100 Subject: gitk: Some improvements for the code for updating the display This should be more robust in the case that some does "Update" before the initial drawing is finished. It also avoids having to reset the list of children for each commit and reconstruct it. Signed-off-by: Paul Mackerras --- gitk | 110 ++++++++++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/gitk b/gitk index 42e96d0e49..2e94145021 100755 --- a/gitk +++ b/gitk @@ -133,14 +133,6 @@ proc getcommitlines {commfd} { set id [lindex $ids 0] set olds [lrange $ids 1 end] set cmit [string range $cmit [expr {$j + 1}] end] - if {$phase == "updatecommits"} { - $canv delete all - set oldcommits $commits - set commits {} - unset children - unset nchildren - set phase getcommits - } lappend commits $id set commitlisted($id) 1 parsecommit $id $cmit 1 [lrange $ids 1 end] @@ -751,7 +743,6 @@ proc assigncolor {id} { proc initgraph {} { global canvy canvy0 lineno numcommits nextcolor linespc - global mainline mainlinearrow sidelines global nchildren ncleft global displist nhyperspace @@ -760,9 +751,11 @@ proc initgraph {} { set canvy $canvy0 set lineno -1 set numcommits 0 - catch {unset mainline} - catch {unset mainlinearrow} - catch {unset sidelines} + foreach v {mainline mainlinearrow sidelines colormap cornercrossings + crossings idline lineid} { + global $v + catch {unset $v} + } foreach id [array names nchildren] { set ncleft($id) $nchildren($id) } @@ -1431,30 +1424,23 @@ proc decidenext {{noread 0}} { } } } - if {$level < 0} { - if {$todo != {}} { - puts "ERROR: none of the pending commits can be done yet:" - foreach p $todo { - puts " $p ($ncleft($p))" - } - } - return -1 - } return $level } proc drawcommit {id reading} { - global phase todo nchildren datemode nextupdate revlistorder - global numcommits ncmupdate displayorder todo onscreen + global phase todo nchildren datemode nextupdate revlistorder ncleft global numcommits ncmupdate displayorder todo onscreen parents + global commitlisted commitordered if {$phase != "incrdraw"} { set phase incrdraw set displayorder {} set todo {} initgraph + catch {unset commitordered} } + set commitordered($id) 1 if {$nchildren($id) == 0} { lappend todo $id set onscreen($id) 0 @@ -1469,18 +1455,16 @@ proc drawcommit {id reading} { updatetodo $level 0 } else { set level [decidenext 1] - if {$level == {} || $id != [lindex $todo $level]} { - return - } + if {$level == {} || $level < 0} return while 1 { + set id [lindex $todo $level] + if {![info exists commitordered($id)]} { + break + } lappend displayorder [lindex $todo $level] if {[updatetodo $level $datemode]} { set level [decidenext 1] - if {$level == {}} break - } - set id [lindex $todo $level] - if {![info exists commitlisted($id)]} { - break + if {$level == {} || $level < 0} break } } } @@ -1490,17 +1474,19 @@ proc drawcommit {id reading} { proc finishcommits {} { global phase oldcommits commits global canv mainfont ctext maincursor textcursor - global parents + global parents displayorder todo if {$phase == "incrdraw" || $phase == "removecommits"} { foreach id $oldcommits { lappend commits $id - updatechildren $id $parents($id) drawcommit $id 0 } set oldcommits {} drawrest } elseif {$phase == "updatecommits"} { + # there were no new commits, in fact + set commits $oldcommits + set oldcommits {} set phase {} } else { $canv delete all @@ -1540,7 +1526,7 @@ proc drawgraph {} { proc drawrest {} { global phase stopped redisplaying selectedline - global datemode todo displayorder + global datemode todo displayorder ncleft global numcommits ncmupdate global nextupdate startmsecs revlistorder @@ -1556,6 +1542,13 @@ proc drawrest {} { } } } + if {$todo != {}} { + puts "ERROR: none of the pending commits can be done yet:" + foreach p $todo { + puts " $p ($ncleft($p))" + } + } + drawmore 0 set phase {} set drawmsecs [expr {[clock clicks -milliseconds] - $startmsecs}] @@ -3637,13 +3630,35 @@ proc updatecommits {rargs} { global idtags idheads idotherrefs global leftover global parsed_args - global canv + global canv mainfont global oldcommits commits global parents nchildren children ncleft set old_args $parsed_args parse_args $rargs + if {$phase == "getcommits" || $phase == "incrdraw"} { + # havent read all the old commits, just start again from scratch + stopfindproc + set oldcommits {} + set commits {} + foreach v {children nchildren parents commitlisted commitinfo + selectedline matchinglines treediffs + mergefilelist currentid rowtextx} { + global $v + catch {unset $v} + } + readrefs + if {$phase == "incrdraw"} { + allcanvs delete all + $canv create text 3 3 -anchor nw -text "Reading commits..." \ + -font $mainfont -tags textitems + set phase getcommits + } + start_rev_list $parsed_args + return + } + foreach id $old_args { if {![regexp {^[0-9a-f]{40}$} $id]} continue if {[info exists oldref($id)]} continue @@ -3664,20 +3679,27 @@ proc updatecommits {rargs} { } set phase updatecommits + set oldcommits $commits + set commits {} set removed_commits [split [eval exec git-rev-list $ignorenew] "\n" ] if {[llength $removed_commits] > 0} { - $canv delete all - set oldcommits {} - foreach c $commits { - if {[lsearch $c $removed_commits] < 0} { - lappend oldcommits $c - } else { + allcanvs delete all + foreach c $removed_commits { + set i [lsearch -exact $oldcommits $c] + if {$i >= 0} { + set oldcommits [lreplace $oldcommits $i $i] unset commitlisted($c) + foreach p $parents($c) { + if {[info exists nchildren($p)]} { + set j [lsearch -exact $children($p) $c] + if {$j >= 0} { + set children($p) [lreplace $children($p) $j $j] + incr nchildren($p) -1 + } + } + } } } - set commits {} - unset children - unset nchildren set phase removecommits } -- cgit v1.2.3 From 4050c0df8ec7043315e2192695de432875239775 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 11:54:29 -0800 Subject: Clean up compatibility definitions. This attempts to clean up the way various compatibility functions are defined and used. - A new header file, git-compat-util.h, is introduced. This looks at various NO_XXX and does necessary function name replacements, equivalent of -Dstrcasestr=gitstrcasestr in the Makefile. - Those function name replacements are removed from the Makefile. - Common features such as usage(), die(), xmalloc() are moved from cache.h to git-compat-util.h; cache.h includes git-compat-util.h itself. Signed-off-by: Junio C Hamano --- Makefile | 12 +++--- cache.h | 96 +------------------------------------------- compat/mmap.c | 2 +- compat/strcasestr.c | 3 +- git-compat-util.h | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++ git.c | 15 +++---- mailinfo.c | 4 -- usage.c | 2 +- 8 files changed, 129 insertions(+), 118 deletions(-) create mode 100644 git-compat-util.h diff --git a/Makefile b/Makefile index df3c6eb81e..425c519ede 100644 --- a/Makefile +++ b/Makefile @@ -162,7 +162,7 @@ LIB_FILE=libgit.a LIB_H = \ blob.h cache.h commit.h count-delta.h csum-file.h delta.h \ diff.h epoch.h object.h pack.h pkt-line.h quote.h refs.h \ - run-command.h strbuf.h tag.h tree.h + run-command.h strbuf.h tag.h tree.h git-compat-util.h DIFF_OBJS = \ diff.o diffcore-break.o diffcore-order.o diffcore-pathspec.o \ @@ -320,15 +320,15 @@ ifdef NEEDS_NSL SIMPLE_LIB += -lnsl endif ifdef NO_STRCASESTR - COMPAT_CFLAGS += -Dstrcasestr=gitstrcasestr -DNO_STRCASESTR=1 + COMPAT_CFLAGS += -DNO_STRCASESTR COMPAT_OBJS += compat/strcasestr.o endif ifdef NO_SETENV - COMPAT_CFLAGS += -Dsetenv=gitsetenv -DNO_SETENV=1 + COMPAT_CFLAGS += -DNO_SETENV COMPAT_OBJS += compat/setenv.o endif ifdef NO_MMAP - COMPAT_CFLAGS += -Dmmap=gitfakemmap -Dmunmap=gitfakemunmap -DNO_MMAP + COMPAT_CFLAGS += -DNO_MMAP COMPAT_OBJS += compat/mmap.o endif ifdef NO_IPV6 @@ -363,9 +363,9 @@ all: $(ALL_PROGRAMS) all: $(MAKE) -C templates -git$(X): git.c $(COMPAT_OBJS) Makefile +git$X: git.c $(LIB_FILE) Makefile $(CC) -DGIT_EXEC_PATH='"$(bindir)"' -DGIT_VERSION='"$(GIT_VERSION)"' \ - $(CFLAGS) $(COMPAT_CFLAGS) -o $@ $(filter %.c,$^) $(filter %.o,$^) + $(CFLAGS) $(COMPAT_CFLAGS) -o $@ $(filter %.c,$^) $(LIB_FILE) $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh rm -f $@ diff --git a/cache.h b/cache.h index f9b367f314..86fc25084c 100644 --- a/cache.h +++ b/cache.h @@ -1,23 +1,7 @@ #ifndef CACHE_H #define CACHE_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef NO_MMAP -#include -#endif -#include -#include -#include -#include +#include "git-compat-util.h" #include SHA1_HEADER #include @@ -36,15 +20,6 @@ #define DTYPE(de) DT_UNKNOWN #endif -#ifdef __GNUC__ -#define NORETURN __attribute__((__noreturn__)) -#else -#define NORETURN -#ifndef __attribute__ -#define __attribute__(x) -#endif -#endif - /* * Intensive research over the course of many years has shown that * port 9418 is totally unused by anything else. Or @@ -250,11 +225,6 @@ extern const char *resolve_ref(const char *path, unsigned char *sha1, int); extern int create_symref(const char *git_HEAD, const char *refs_heads_master); extern int validate_symref(const char *git_HEAD); -/* General helper functions */ -extern void usage(const char *err) NORETURN; -extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); -extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); - extern int base_name_compare(const char *name1, int len1, int mode1, const char *name2, int len2, int mode2); extern int cache_name_compare(const char *name1, int len1, const char *name2, int len2); @@ -272,30 +242,6 @@ extern int setup_ident(void); extern const char *git_author_info(void); extern const char *git_committer_info(void); -static inline void *xmalloc(size_t size) -{ - void *ret = malloc(size); - if (!ret) - die("Out of memory, malloc failed"); - return ret; -} - -static inline void *xrealloc(void *ptr, size_t size) -{ - void *ret = realloc(ptr, size); - if (!ret) - die("Out of memory, realloc failed"); - return ret; -} - -static inline void *xcalloc(size_t nmemb, size_t size) -{ - void *ret = calloc(nmemb, size); - if (!ret) - die("Out of memory, calloc failed"); - return ret; -} - struct checkout { const char *base_dir; int base_dir_len; @@ -373,20 +319,6 @@ extern void packed_object_info_detail(struct pack_entry *, char *, unsigned long /* Dumb servers support */ extern int update_server_info(int); -#ifdef NO_MMAP - -#ifndef PROT_READ -#define PROT_READ 1 -#define PROT_WRITE 2 -#define MAP_PRIVATE 1 -#define MAP_FAILED ((void*)-1) -#endif - -extern void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); -extern int gitfakemunmap(void *start, size_t length); - -#endif - typedef int (*config_fn_t)(const char *, const char *); extern int git_default_config(const char *, const char *); extern int git_config_from_file(config_fn_t fn, const char *); @@ -404,31 +336,5 @@ extern char git_default_name[MAX_GITNAME]; #define MAX_ENCODING_LENGTH 64 extern char git_commit_encoding[MAX_ENCODING_LENGTH]; -/* Sane ctype - no locale, and works with signed chars */ -#undef isspace -#undef isdigit -#undef isalpha -#undef isalnum -#undef tolower -#undef toupper -extern unsigned char sane_ctype[256]; -#define GIT_SPACE 0x01 -#define GIT_DIGIT 0x02 -#define GIT_ALPHA 0x04 -#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) -#define isspace(x) sane_istest(x,GIT_SPACE) -#define isdigit(x) sane_istest(x,GIT_DIGIT) -#define isalpha(x) sane_istest(x,GIT_ALPHA) -#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) -#define tolower(x) sane_case((unsigned char)(x), 0x20) -#define toupper(x) sane_case((unsigned char)(x), 0) - -static inline int sane_case(int x, int high) -{ - if (sane_istest(x, GIT_ALPHA)) - x = (x & ~0x20) | high; - return x; -} - extern int copy_fd(int ifd, int ofd); #endif /* CACHE_H */ diff --git a/compat/mmap.c b/compat/mmap.c index a051c4767d..55cb120764 100644 --- a/compat/mmap.c +++ b/compat/mmap.c @@ -2,7 +2,7 @@ #include #include #include -#include "../cache.h" +#include "../git-compat-util.h" void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset) { diff --git a/compat/strcasestr.c b/compat/strcasestr.c index b96414d36b..26896deca6 100644 --- a/compat/strcasestr.c +++ b/compat/strcasestr.c @@ -1,5 +1,4 @@ -#include -#include +#include "../git-compat-util.h" char *gitstrcasestr(const char *haystack, const char *needle) { diff --git a/git-compat-util.h b/git-compat-util.h new file mode 100644 index 0000000000..4185b12741 --- /dev/null +++ b/git-compat-util.h @@ -0,0 +1,113 @@ +#ifndef GIT_COMPAT_UTIL_H +#define GIT_COMPAT_UTIL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ +#define NORETURN __attribute__((__noreturn__)) +#else +#define NORETURN +#ifndef __attribute__ +#define __attribute__(x) +#endif +#endif + +/* General helper functions */ +extern void usage(const char *err) NORETURN; +extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2))); +extern int error(const char *err, ...) __attribute__((format (printf, 1, 2))); + +#ifdef NO_MMAP + +#ifndef PROT_READ +#define PROT_READ 1 +#define PROT_WRITE 2 +#define MAP_PRIVATE 1 +#define MAP_FAILED ((void*)-1) +#endif + +#define mmap gitfakemmap +#define munmap gitfakemunmap +extern void *gitfakemmap(void *start, size_t length, int prot , int flags, int fd, off_t offset); +extern int gitfakemunmap(void *start, size_t length); + +#else /* NO_MMAP */ + +#include + +#endif /* NO_MMAP */ + +#ifdef NO_SETENV +#define setenv gitsetenv +extern int gitsetenv(const char *, const char *, int); +#endif + +#ifdef NO_STRCASESTR +#define strcasestr gitstrcasestr +extern char *gitstrcasestr(const char *haystack, const char *needle); +#endif + +static inline void *xmalloc(size_t size) +{ + void *ret = malloc(size); + if (!ret) + die("Out of memory, malloc failed"); + return ret; +} + +static inline void *xrealloc(void *ptr, size_t size) +{ + void *ret = realloc(ptr, size); + if (!ret) + die("Out of memory, realloc failed"); + return ret; +} + +static inline void *xcalloc(size_t nmemb, size_t size) +{ + void *ret = calloc(nmemb, size); + if (!ret) + die("Out of memory, calloc failed"); + return ret; +} + +/* Sane ctype - no locale, and works with signed chars */ +#undef isspace +#undef isdigit +#undef isalpha +#undef isalnum +#undef tolower +#undef toupper +extern unsigned char sane_ctype[256]; +#define GIT_SPACE 0x01 +#define GIT_DIGIT 0x02 +#define GIT_ALPHA 0x04 +#define sane_istest(x,mask) ((sane_ctype[(unsigned char)(x)] & (mask)) != 0) +#define isspace(x) sane_istest(x,GIT_SPACE) +#define isdigit(x) sane_istest(x,GIT_DIGIT) +#define isalpha(x) sane_istest(x,GIT_ALPHA) +#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) +#define tolower(x) sane_case((unsigned char)(x), 0x20) +#define toupper(x) sane_case((unsigned char)(x), 0) + +static inline int sane_case(int x, int high) +{ + if (sane_istest(x, GIT_ALPHA)) + x = (x & ~0x20) | high; + return x; +} + +#endif diff --git a/git.c b/git.c index ee5048aaaa..c26cac6555 100644 --- a/git.c +++ b/git.c @@ -8,15 +8,12 @@ #include #include #include +#include "git-compat-util.h" #ifndef PATH_MAX # define PATH_MAX 4096 #endif -#ifdef NO_SETENV -extern int gitsetenv(const char *, const char *, int); -#endif - static const char git_usage[] = "Usage: git [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ ARGS ]"; @@ -156,10 +153,10 @@ static void list_commands(const char *exec_path, const char *pattern) } #ifdef __GNUC__ -static void usage(const char *exec_path, const char *fmt, ...) +static void cmd_usage(const char *exec_path, const char *fmt, ...) __attribute__((__format__(__printf__, 2, 3), __noreturn__)); #endif -static void usage(const char *exec_path, const char *fmt, ...) +static void cmd_usage(const char *exec_path, const char *fmt, ...) { if (fmt) { va_list ap; @@ -254,12 +251,12 @@ int main(int argc, char **argv, char **envp) else if (!strcmp(arg, "help")) show_help = 1; else if (!show_help) - usage(NULL, NULL); + cmd_usage(NULL, NULL); } if (i >= argc || show_help) { if (i >= argc) - usage(exec_path, NULL); + cmd_usage(exec_path, NULL); show_man_page(argv[i]); } @@ -297,7 +294,7 @@ int main(int argc, char **argv, char **envp) execve(git_command, &argv[i], envp); if (errno == ENOENT) - usage(exec_path, "'%s' is not a git-command", argv[i]); + cmd_usage(exec_path, "'%s' is not a git-command", argv[i]); fprintf(stderr, "Failed to run command '%s': %s\n", git_command, strerror(errno)); diff --git a/mailinfo.c b/mailinfo.c index 890e3487ad..3b97a893f0 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -10,10 +10,6 @@ #include #include "cache.h" -#ifdef NO_STRCASESTR -extern char *gitstrcasestr(const char *haystack, const char *needle); -#endif - static FILE *cmitmsg, *patchfile; static int keep_subject = 0; diff --git a/usage.c b/usage.c index dfa87fe119..1fa924c3d9 100644 --- a/usage.c +++ b/usage.c @@ -3,7 +3,7 @@ * * Copyright (C) Linus Torvalds, 2005 */ -#include "cache.h" +#include "git-compat-util.h" static void report(const char *prefix, const char *err, va_list params) { -- cgit v1.2.3 From 8d69195124c826756c025fc84d993d92ff119075 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 18:13:31 -0800 Subject: Fix 5501 test Not everybody can rely on /bin/sh to be sane, and we support SHELL_PATH for that. Use it. mktemp(1) is not used anywhere else in the core git. Do not introduce dependency on it. Not everybody's "which" gives a sane return value. For example, on Solaris 'which XXX' says "no XXX in /usr/bin /bin ..." and exits with zero status. The lesson here is to never use 'which' in your scripts. Signed-off-by: Junio C Hamano Signed-off-by: Junio C Hamano --- t/t5501-old-fetch-and-upload.sh | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/t/t5501-old-fetch-and-upload.sh b/t/t5501-old-fetch-and-upload.sh index ada5130328..596c88b1c2 100755 --- a/t/t5501-old-fetch-and-upload.sh +++ b/t/t5501-old-fetch-and-upload.sh @@ -7,8 +7,9 @@ # an old counterpart cd $(dirname $0) || exit 1 +: ${SHELL_PATH=/bin/sh} -tmp=$(mktemp /tmp/tmp-XXXXXXXX) +tmp=`pwd`/.tmp$$ retval=0 @@ -25,13 +26,17 @@ for i in $list; do both) pgm="old-git-upload-pack"; replace="old-git-fetch-pack --exec=$pgm";; esac - if which $pgm 2>/dev/null; then + if where=`LANG=C LC_ALL=C which "$pgm" 2>/dev/null` && + case "$where" in + "no "*) (exit 1) ;; + esac + then echo "Testing with $pgm" sed -e "s/git-fetch-pack/$replace/g" \ -e "s/# old fails/warn/" < t5500-fetch-pack.sh > $tmp - sh $tmp || retval=$? - rm $tmp + "$SHELL_PATH" "$tmp" || retval=$? + rm -f "$tmp" test $retval != 0 && exit $retval else -- cgit v1.2.3 From 23c99d84601316c1e51ebc1f0b9bec5cddd011fb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 18:14:34 -0800 Subject: git-mv to work with Perl 5.6 List form of pipe open is 5.8 invention. Signed-off-by: Junio C Hamano --- git-mv.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-mv.perl b/git-mv.perl index b6c0b48818..83dc7e45cf 100755 --- a/git-mv.perl +++ b/git-mv.perl @@ -62,7 +62,7 @@ my $safesrc; my (%overwritten, %srcForDst); $/ = "\0"; -open(F,"-|","git-ls-files","-z") +open(F, 'git-ls-files -z |') or die "Failed to open pipe from git-ls-files: " . $!; @allfiles = map { chomp; $_; } ; -- cgit v1.2.3 From 61f693bd5a2ab4d830aad6fce0a1c70863f38009 Mon Sep 17 00:00:00 2001 From: Jon Loeliger Date: Mon, 5 Dec 2005 23:13:03 -0600 Subject: Added documentation for few missing options. More $ shell prompts in examples. Minor English grammar improvements. Added a few "See Also"s. Use back-ticks on more command examples. Signed-off-by: Jon Loeliger Signed-off-by: Junio C Hamano --- Documentation/git-checkout-index.txt | 72 ++++++++++++++++++++++------------- Documentation/git-init-db.txt | 27 +++++++++++-- Documentation/git-prune-packed.txt | 11 ++++-- Documentation/git-read-tree.txt | 74 ++++++++++++++++++++---------------- Documentation/git-update-index.txt | 20 +++++++--- Documentation/git-write-tree.txt | 14 ++++--- 6 files changed, 139 insertions(+), 79 deletions(-) diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt index 5bff4865f7..97eef22ccd 100644 --- a/Documentation/git-checkout-index.txt +++ b/Documentation/git-checkout-index.txt @@ -45,53 +45,71 @@ OPTIONS The order of the flags used to matter, but not anymore. -Just doing "git-checkout-index" does nothing. You probably meant -"git-checkout-index -a". And if you want to force it, you want -"git-checkout-index -f -a". +Just doing `git-checkout-index` does nothing. You probably meant +`git-checkout-index -a`. And if you want to force it, you want +`git-checkout-index -f -a`. Intuitiveness is not the goal here. Repeatability is. The reason for -the "no arguments means no work" thing is that from scripts you are -supposed to be able to do things like: +the "no arguments means no work" behavior is that from scripts you are +supposed to be able to do: - find . -name '*.h' -print0 | xargs -0 git-checkout-index -f -- +---------------- +$ find . -name '*.h' -print0 | xargs -0 git-checkout-index -f -- +---------------- which will force all existing `*.h` files to be replaced with their cached copies. If an empty command line implied "all", then this would force-refresh everything in the index, which was not the point. -To update and refresh only the files already checked out: +The `--` is just a good idea when you know the rest will be filenames; +it will prevent problems with a filename of, for example, `-a`. +Using `--` is probably a good policy in scripts. - git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh -Oh, and the "--" is just a good idea when you know the rest will be -filenames. Just so that you wouldn't have a filename of "-a" causing -problems (not possible in the above example, but get used to it in -scripting!). - -The prefix ability basically makes it trivial to use -git-checkout-index as an "export as tree" function. Just read the -desired tree into the index, and do a - - git-checkout-index --prefix=git-export-dir/ -a - -and git-checkout-index will "export" the index into the specified +EXAMPLES +-------- +To update and refresh only the files already checked out:: ++ +---------------- +$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh +---------------- + +Using `git-checkout-index` to "export an entire tree":: + The prefix ability basically makes it trivial to use + `git-checkout-index` as an "export as tree" function. + Just read the desired tree into the index, and do: ++ +---------------- +$ git-checkout-index --prefix=git-export-dir/ -a +---------------- ++ +`git-checkout-index` will "export" the index into the specified directory. ++ +The final "/" is important. The exported name is literally just +prefixed with the specified string. Contrast this with the +following example. -NOTE The final "/" is important. The exported name is literally just -prefixed with the specified string, so you can also do something like +Export files with a prefix:: ++ +---------------- +$ git-checkout-index --prefix=.merged- Makefile +---------------- ++ +This will check out the currently cached copy of `Makefile` +into the file `.merged-Makefile`. - git-checkout-index --prefix=.merged- Makefile - -to check out the currently cached copy of `Makefile` into the file -`.merged-Makefile` Author ------ Written by Linus Torvalds + Documentation -------------- -Documentation by David Greaves, Junio C Hamano and the git-list . +Documentation by David Greaves, +Junio C Hamano and the git-list . + GIT --- diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt index ef1826ae67..4486f0c1cf 100644 --- a/Documentation/git-init-db.txt +++ b/Documentation/git-init-db.txt @@ -8,7 +8,14 @@ git-init-db - Creates an empty git repository SYNOPSIS -------- -'git-init-db' +'git-init-db' [--template=] + + +OPTIONS +------- +--template=:: + Provide the directory in from which templates will be used. + DESCRIPTION ----------- @@ -16,14 +23,26 @@ This simply creates an empty git repository - basically a `.git` directory and `.git/object/??/`, `.git/refs/heads` and `.git/refs/tags` directories, and links `.git/HEAD` symbolically to `.git/refs/heads/master`. -If the 'GIT_DIR' environment variable is set then it specifies a path +If the `$GIT_DIR` environment variable is set then it specifies a path to use instead of `./.git` for the base of the repository. -If the object storage directory is specified via the 'GIT_OBJECT_DIRECTORY' +If the object storage directory is specified via the `$GIT_OBJECT_DIRECTORY` environment variable then the sha1 directories are created underneath - otherwise the default `$GIT_DIR/objects` directory is used. -"git-init-db" won't hurt an existing repository. +`git-init-db` won't hurt an existing repository. + + +EXAMPLES +-------- + +Start a new git repository for an existing code base:: ++ +---------------- +$ cd /path/to/my/codebase +$ git-init-db +---------------- + Author diff --git a/Documentation/git-prune-packed.txt b/Documentation/git-prune-packed.txt index 8d96a91b41..37c53a91de 100644 --- a/Documentation/git-prune-packed.txt +++ b/Documentation/git-prune-packed.txt @@ -9,19 +9,22 @@ residing in a pack file. SYNOPSIS -------- -'git-prune-packed' +'git-prune-packed' [-n] + DESCRIPTION ----------- -This program search the GIT_OBJECT_DIR for all objects that currently exist in -a pack file as well as the independent object directories. +This program search the `$GIT_OBJECT_DIR` for all objects that currently +exist in a pack file as well as the independent object directories. All such extra objects are removed. A pack is a collection of objects, individually compressed, with delta compression applied, stored in a single file, with an associated index file. -Packs are used to reduce the load on mirror systems, backup engines, disk storage, etc. +Packs are used to reduce the load on mirror systems, backup engines, +disk storage, etc. + OPTIONS ------- diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index 6e92e4aa66..4377362df2 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -15,15 +15,15 @@ DESCRIPTION ----------- Reads the tree information given by into the index, but does not actually *update* any of the files it "caches". (see: -git-checkout-index) +gitlink:git-checkout-index[1]) Optionally, it can merge a tree into the index, perform a -fast-forward (i.e. 2-way) merge, or a 3-way merge, with the -m -flag. When used with -m, the -u flag causes it to also update +fast-forward (i.e. 2-way) merge, or a 3-way merge, with the `-m` +flag. When used with `-m`, the `-u` flag causes it to also update the files in the work tree with the result of the merge. -Trivial merges are done by "git-read-tree" itself. Only conflicting paths -will be in unmerged state when "git-read-tree" returns. +Trivial merges are done by `git-read-tree` itself. Only conflicting paths +will be in unmerged state when `git-read-tree` returns. OPTIONS ------- @@ -56,7 +56,7 @@ OPTIONS Merging ------- -If '-m' is specified, "git-read-tree" can perform 3 kinds of +If `-m` is specified, `git-read-tree` can perform 3 kinds of merge, a single tree merge if only 1 tree is given, a fast-forward merge with 2 trees, or a 3-way merge if 3 trees are provided. @@ -65,23 +65,23 @@ provided. Single Tree Merge ~~~~~~~~~~~~~~~~~ If only 1 tree is specified, git-read-tree operates as if the user did not -specify '-m', except that if the original index has an entry for a +specify `-m`, except that if the original index has an entry for a given pathname, and the contents of the path matches with the tree being read, the stat info from the index is used. (In other words, the index's stat()s take precedence over the merged tree's). -That means that if you do a "git-read-tree -m " followed by a -"git-checkout-index -f -u -a", the "git-checkout-index" only checks out +That means that if you do a `git-read-tree -m ` followed by a +`git-checkout-index -f -u -a`, the `git-checkout-index` only checks out the stuff that really changed. -This is used to avoid unnecessary false hits when "git-diff-files" is -run after git-read-tree. +This is used to avoid unnecessary false hits when `git-diff-files` is +run after `git-read-tree`. Two Tree Merge ~~~~~~~~~~~~~~ -Typically, this is invoked as "git-read-tree -m $H $M", where $H +Typically, this is invoked as `git-read-tree -m $H $M`, where $H is the head commit of the current repository, and $M is the head of a foreign tree, which is simply ahead of $H (i.e. we are in a fast forward situation). @@ -94,7 +94,7 @@ the following: 2. The user wants to fast-forward to $M. -In this case, the "git-read-tree -m $H $M" command makes sure +In this case, the `git-read-tree -m $H $M` command makes sure that no local change is lost as the result of this "merge". Here are the "carry forward" rules: @@ -141,13 +141,13 @@ operating under the -u flag. When this form of git-read-tree returns successfully, you can see what "local changes" you made are carried forward by running -"git-diff-index --cached $M". Note that this does not -necessarily match "git-diff-index --cached $H" would have +`git-diff-index --cached $M`. Note that this does not +necessarily match `git-diff-index --cached $H` would have produced before such a two tree merge. This is because of cases 18 and 19 --- if you already had the changes in $M (e.g. maybe -you picked it up via e-mail in a patch form), "git-diff-index ---cached $H" would have told you about the change before this -merge, but it would not show in "git-diff-index --cached $M" +you picked it up via e-mail in a patch form), `git-diff-index +--cached $H` would have told you about the change before this +merge, but it would not show in `git-diff-index --cached $M` output after two-tree merge. @@ -156,18 +156,20 @@ output after two-tree merge. Each "index" entry has two bits worth of "stage" state. stage 0 is the normal one, and is the only one you'd see in any kind of normal use. -However, when you do "git-read-tree" with three trees, the "stage" +However, when you do `git-read-tree` with three trees, the "stage" starts out at 1. This means that you can do - git-read-tree -m +---------------- +$ git-read-tree -m +---------------- and you will end up with an index with all of the entries in "stage1", all of the entries in "stage2" and all of the entries in "stage3". -Furthermore, "git-read-tree" has special-case logic that says: if you see +Furthermore, `git-read-tree` has special-case logic that says: if you see a file that matches in all respects in the following states, it "collapses" back to "stage0": @@ -180,7 +182,7 @@ a file that matches in all respects in the following states, it - stage 1 and stage 3 are the same and stage 2 is different take stage 2 (some work has been done on stage 2) -The "git-write-tree" command refuses to write a nonsensical tree, and it +The `git-write-tree` command refuses to write a nonsensical tree, and it will complain about unmerged entries if it sees a single entry that is not stage 0. @@ -220,8 +222,8 @@ populated. Here is an outline of how the algorithm works: matching "stage1" entry if it exists too. .. all the normal trivial rules .. -You would normally use "git-merge-index" with supplied -"git-merge-one-file" to do this last step. The script +You would normally use `git-merge-index` with supplied +`git-merge-one-file` to do this last step. The script does not touch the files in the work tree, and the entire merge happens in the index file. In other words, there is no need to worry about what is in the working directory, since it is never @@ -239,27 +241,33 @@ This is done to prevent you from losing your work-in-progress changes. To illustrate, suppose you start from what has been commited last to your repository: - $ JC=`git-rev-parse --verify "HEAD^0"` - $ git-checkout-index -f -u -a $JC +---------------- +$ JC=`git-rev-parse --verify "HEAD^0"` +$ git-checkout-index -f -u -a $JC +---------------- You do random edits, without running git-update-index. And then you notice that the tip of your "upstream" tree has advanced since you pulled from him: - $ git-fetch rsync://.... linus - $ LT=`cat .git/MERGE_HEAD` +---------------- +$ git-fetch rsync://.... linus +$ LT=`cat .git/MERGE_HEAD` +---------------- Your work tree is still based on your HEAD ($JC), but you have some edits since. Three-way merge makes sure that you have not added or modified index entries since $JC, and if you haven't, then does the right thing. So with the following sequence: - $ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT - $ git-merge-index git-merge-one-file -a - $ echo "Merge with Linus" | \ - git-commit-tree `git-write-tree` -p $JC -p $LT +---------------- +$ git-read-tree -m -u `git-merge-base $JC $LT` $JC $LT +$ git-merge-index git-merge-one-file -a +$ echo "Merge with Linus" | \ + git-commit-tree `git-write-tree` -p $JC -p $LT +---------------- -what you would commit is a pure merge between $JC and LT without +what you would commit is a pure merge between $JC and $LT without your work-in-progress changes, and your work tree would be updated to the result of the merge. diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index fdcb8bea7d..e4678cd280 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -123,7 +123,9 @@ merging. To pretend you have a file with mode and sha1 at path, say: - $ git-update-index --cacheinfo mode sha1 path +---------------- +$ git-update-index --cacheinfo mode sha1 path +---------------- '--info-only' is used to register files without placing them in the object database. This is useful for status-only repositories. @@ -138,7 +140,9 @@ Examples -------- To update and refresh only the files already checked out: - git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh +---------------- +$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh +---------------- Configuration @@ -146,12 +150,18 @@ Configuration The command honors `core.filemode` configuration variable. If your repository is on an filesystem whose executable bits are -unreliable, this should be set to 'false'. This causes the -command to ignore differences in file modes recorded in the -index and the file mode on the filesystem if they differ only on +unreliable, this should be set to 'false' (see gitlink:git-repo-config[1]). +This causes the command to ignore differences in file modes recorded +in the index and the file mode on the filesystem if they differ only on executable bit. On such an unfortunate filesystem, you may need to use `git-update-index --chmod=`. + +See Also +-------- +gitlink:git-repo-config[1] + + Author ------ Written by Linus Torvalds diff --git a/Documentation/git-write-tree.txt b/Documentation/git-write-tree.txt index abee05f6f5..77e12cb949 100644 --- a/Documentation/git-write-tree.txt +++ b/Documentation/git-write-tree.txt @@ -14,19 +14,21 @@ DESCRIPTION ----------- Creates a tree object using the current index. -The index must be merged. +The index must be in a fully merged state. -Conceptually, "git-write-tree" sync()s the current index contents +Conceptually, `git-write-tree` sync()s the current index contents into a set of tree files. In order to have that match what is actually in your directory right -now, you need to have done a "git-update-index" phase before you did the -"git-write-tree". +now, you need to have done a `git-update-index` phase before you did the +`git-write-tree`. + OPTIONS ------- --missing-ok:: - Normally "git-write-tree" ensures that the objects referenced by the - directory exist in the object database. This option disables this check. + Normally `git-write-tree` ensures that the objects referenced by the + directory exist in the object database. This option disables this + check. Author ------ -- cgit v1.2.3 From 9c2e7c0ca240e1508871cd22f2ee380f52d69a53 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 22:29:05 -0800 Subject: hash-object: -- and --help It was cumbersome to feed hash-object the file '-t' (you could have said "./-t", though). Teach it '--' that terminates the option list, like everybody else. There is no way to extract usage string from the command either, so teach it "--help" as well. Signed-off-by: Junio C Hamano --- hash-object.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/hash-object.c b/hash-object.c index ccba11cb32..62279368b8 100644 --- a/hash-object.c +++ b/hash-object.c @@ -31,19 +31,30 @@ int main(int argc, char **argv) int write_object = 0; const char *prefix = NULL; int prefix_length = -1; + int no_more_flags = 0; for (i = 1 ; i < argc; i++) { - if (!strcmp(argv[i], "-t")) { - if (argc <= ++i) - die(hash_object_usage); - type = argv[i]; - } - else if (!strcmp(argv[i], "-w")) { - if (prefix_length < 0) { - prefix = setup_git_directory(); - prefix_length = prefix ? strlen(prefix) : 0; + if (!no_more_flags && argv[i][0] == '-') { + if (!strcmp(argv[i], "-t")) { + if (argc <= ++i) + die(hash_object_usage); + type = argv[i]; + } + else if (!strcmp(argv[i], "-w")) { + if (prefix_length < 0) { + prefix = setup_git_directory(); + prefix_length = + prefix ? strlen(prefix) : 0; + } + write_object = 1; } - write_object = 1; + else if (!strcmp(argv[i], "--")) { + no_more_flags = 1; + } + else if (!strcmp(argv[i], "--help")) + usage(hash_object_usage); + else + die(hash_object_usage); } else { const char *arg = argv[i]; @@ -51,6 +62,7 @@ int main(int argc, char **argv) arg = prefix_filename(prefix, prefix_length, arg); hash_object(arg, type, write_object); + no_more_flags = 1; } } return 0; -- cgit v1.2.3 From 4a62eaed317e260b0bdb0ce5f340757d2a6dfef1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 22:29:36 -0800 Subject: init-db: check extra arguments and complain. "git-init-db junk" does not complain but just ignores "junk". Die with the usage string in such a case. Signed-off-by: Junio C Hamano --- init-db.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/init-db.c b/init-db.c index 8195b6842e..ead37b5ed8 100644 --- a/init-db.c +++ b/init-db.c @@ -237,9 +237,7 @@ int main(int argc, char **argv) for (i = 1; i < argc; i++, argv++) { char *arg = argv[1]; - if (arg[0] != '-') - break; - else if (!strncmp(arg, "--template=", 11)) + if (!strncmp(arg, "--template=", 11)) template_dir = arg+11; else die(init_db_usage); -- cgit v1.2.3 From 75a46f6b0ed3c3aa6fe4ff53a8c20cb58cbb3732 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 22:30:07 -0800 Subject: write-tree: check extra arguments and die but be a bit more helpful. "git-write-tree junk" complains and dies, but it does not say what option it supports. Die with the usage string in such a case. Signed-off-by: Junio C Hamano --- write-tree.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/write-tree.c b/write-tree.c index 0aac32f227..f866059f24 100644 --- a/write-tree.c +++ b/write-tree.c @@ -83,6 +83,8 @@ static int write_tree(struct cache_entry **cachep, int maxentries, const char *b return nr; } +static const char write_tree_usage[] = "git-write-tree [--missing-ok]"; + int main(int argc, char **argv) { int i, funny; @@ -96,7 +98,7 @@ int main(int argc, char **argv) if (!strcmp(argv[1], "--missing-ok")) missing_ok = 1; else - die("unknown option %s", argv[1]); + die(write_tree_usage); } if (argc > 2) -- cgit v1.2.3 From 5f6da1d9d2b073c72d3588518934ade16df51268 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 22:36:22 -0800 Subject: Documentation: hash-object. The file parameter is better spelled just "file", not "any file on the filesystem". We stress that in the description text later anyway. Signed-off-by: Junio C Hamano --- Documentation/git-hash-object.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt index 07d2c427c5..db12e926f8 100644 --- a/Documentation/git-hash-object.txt +++ b/Documentation/git-hash-object.txt @@ -8,7 +8,7 @@ git-hash-object - Computes object ID and optionally creates a blob from a file. SYNOPSIS -------- -'git-hash-object' [-t ] [-w] +'git-hash-object' [-t ] [-w] DESCRIPTION ----------- -- cgit v1.2.3 From bb6d7b893e7f9f22e58a63d871b5b4c87b887513 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 5 Dec 2005 23:26:10 -0800 Subject: Documentaiton (read-tree): update description of 3-way The merge-one-file used to leave the working tree intact, but it has long been changed to leave the merge result there since 2a68a8659f7dc55fd285d235ae2d19e7a8116c30 commit. Signed-off-by: Junio C Hamano --- Documentation/git-read-tree.txt | 43 +++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index 4377362df2..27ee5909c9 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -167,20 +167,26 @@ $ git-read-tree -m and you will end up with an index with all of the entries in "stage1", all of the entries in "stage2" and all of the - entries in "stage3". + entries in "stage3". When performing a merge of another +branch into the current branch, we use the common ancestor tree +as , the current branch head as , and the other +branch head as . Furthermore, `git-read-tree` has special-case logic that says: if you see a file that matches in all respects in the following states, it "collapses" back to "stage0": - stage 2 and 3 are the same; take one or the other (it makes no - difference - the same work has been done on stage 2 and 3) + difference - the same work has been done on our branch in + stage 2 and their branch in stage 3) - stage 1 and stage 2 are the same and stage 3 is different; take - stage 3 (some work has been done on stage 3) + stage 3 (our branch in stage 2 did not do anything since the + ancestor in stage 1 while their branch in stage 3 worked on + it) - stage 1 and stage 3 are the same and stage 2 is different take - stage 2 (some work has been done on stage 2) + stage 2 (we did something while they did nothing) The `git-write-tree` command refuses to write a nonsensical tree, and it will complain about unmerged entries if it sees a single entry that is not @@ -223,11 +229,9 @@ populated. Here is an outline of how the algorithm works: trivial rules .. You would normally use `git-merge-index` with supplied -`git-merge-one-file` to do this last step. The script -does not touch the files in the work tree, and the entire merge -happens in the index file. In other words, there is no need to -worry about what is in the working directory, since it is never -shown and never used. +`git-merge-one-file` to do this last step. The script updates +the files in the working tree as it merges each path and at the +end of a successful merge. When you start a 3-way merge with an index file that is already populated, it is assumed that it represents the state of the @@ -238,7 +242,8 @@ merge refuses to run if it finds an entry in the original index file that does not match stage 2. This is done to prevent you from losing your work-in-progress -changes. To illustrate, suppose you start from what has been +changes, and mixing your random changes in an unrelated merge +commit. To illustrate, suppose you start from what has been commited last to your repository: ---------------- @@ -251,8 +256,8 @@ you notice that the tip of your "upstream" tree has advanced since you pulled from him: ---------------- -$ git-fetch rsync://.... linus -$ LT=`cat .git/MERGE_HEAD` +$ git-fetch git://.... linus +$ LT=`cat .git/FETCH_HEAD` ---------------- Your work tree is still based on your HEAD ($JC), but you have @@ -271,6 +276,20 @@ what you would commit is a pure merge between $JC and $LT without your work-in-progress changes, and your work tree would be updated to the result of the merge. +However, if you have local changes in the working tree that +would be overwritten by this merge,`git-read-tree` will refuse +to run to prevent your changes from being lost. + +In other words, there is no need to worry about what exists only +in the working tree. When you have local changes in a part of +the project that is not involved in the merge, your changes do +not interfere with the merge, and are kept intact. When they +*do* interfere, the merge does not even start (`git-read-tree` +complains loudly and fails without modifying anything). In such +a case, you can simply continue doing what you were in the +middle of doing, and when your working tree is ready (i.e. you +have finished your work-in-progress), attempt the merge again. + See Also -------- -- cgit v1.2.3 From be61db922a230ae2638c27c071ee4b8c98f01f72 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 6 Dec 2005 00:07:58 -0800 Subject: git-merge-one-file: resurrect leading path creation. Since we do not use git-update-index followed by git-checkout-index -u to create the half-merged file on conflicting case anymore, we need to make sure the leading directories are created here. Maybe a better solution would be to allow update-index to add to higher stage, and checkout-index to extract from such, but that is a change slightly bigger than I would like to have so close to 1.0, so this should do for now. Signed-off-by: Junio C Hamano --- git-merge-one-file.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh index eafef770db..88a5da99f6 100755 --- a/git-merge-one-file.sh +++ b/git-merge-one-file.sh @@ -16,6 +16,14 @@ # been handled already by git-read-tree, but that one doesn't # do any merges that might change the tree layout. +verify_path() { + file="$1" + dir=`dirname "$file"` && + mkdir -p "$dir" && + rm -f -- "$file" && + : >"$file" +} + case "${1:-.}${2:-.}${3:-.}" in # # Deleted in both or deleted in one and unchanged in the other @@ -90,9 +98,9 @@ case "${1:-.}${2:-.}${3:-.}" in # Create the working tree file, with the correct permission bits. # we can not rely on the fact that our tree has the path, because # we allow the merge to be done in an unchecked-out working tree. - rm -f "$4" && + verify_path "$4" && git-cat-file blob "$2" >"$4" && - case "$6" in *7??) chmod +x "$4" ;; esac && + case "$6" in *7??) chmod +x -- "$4" ;; esac && merge "$4" "$orig" "$src2" ret=$? rm -f -- "$orig" "$src2" -- cgit v1.2.3 From a6da9395a5b6d3df901ce0a6cb61d123f77d7342 Mon Sep 17 00:00:00 2001 From: Jason Riedy Date: Tue, 6 Dec 2005 14:20:16 -0800 Subject: [PATCH] Initial AIX portability fixes. Added an AIX clause in the Makefile; that clause likely will be wrong for any AIX pre-5.2, but I can only test on 5.3. mailinfo.c was missing the compat header file, and convert-objects.c needs to define a specific _XOPEN_SOURCE as well as _XOPEN_SOURCE_EXTENDED. Signed-off-by: E. Jason Riedy Signed-off-by: Junio C Hamano --- Makefile | 4 ++++ convert-objects.c | 3 ++- mailinfo.c | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 425c519ede..01b6643bdf 100644 --- a/Makefile +++ b/Makefile @@ -243,6 +243,10 @@ ifeq ($(uname_S),NetBSD) ALL_CFLAGS += -I/usr/pkg/include ALL_LDFLAGS += -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib endif +ifeq ($(uname_S),AIX) + NO_STRCASESTR=YesPlease + NEEDS_LIBICONV=YesPlease +endif ifneq (,$(findstring arm,$(uname_M))) ARM_SHA1 = YesPlease endif diff --git a/convert-objects.c b/convert-objects.c index d78a8b4ae3..b49bce2681 100644 --- a/convert-objects.c +++ b/convert-objects.c @@ -1,4 +1,5 @@ -#define _XOPEN_SOURCE /* glibc2 needs this */ +#define _XOPEN_SOURCE 500 /* glibc2 and AIX 5.3L need this */ +#define _XOPEN_SOURCE_EXTENDED 1 /* AIX 5.3L needs this */ #include #include "cache.h" diff --git a/mailinfo.c b/mailinfo.c index 3b97a893f0..d4b4163628 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -8,6 +8,7 @@ #include #include #include +#include "git-compat-util.h" #include "cache.h" static FILE *cmitmsg, *patchfile; -- cgit v1.2.3 From e23eff8be92a2a2cb66b53deef020063cff285ed Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 6 Dec 2005 13:41:48 -0800 Subject: qsort() ptrdiff_t may be larger than int Morten Welinder writes: > The code looks wrong. It assumes that pointers are no larger than ints. > If pointers are larger than ints, the code does not necessarily compute > a consistent ordering and qsort is allowed to do whatever it wants. > > Morten > > static int compare_object_pointers(const void *a, const void *b) > { > const struct object * const *pa = a; > const struct object * const *pb = b; > return *pa - *pb; > } Signed-off-by: Junio C Hamano --- object.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/object.c b/object.c index 427e14cae2..cf5931a942 100644 --- a/object.c +++ b/object.c @@ -82,7 +82,12 @@ static int compare_object_pointers(const void *a, const void *b) { const struct object * const *pa = a; const struct object * const *pb = b; - return *pa - *pb; + if (*pa == *pb) + return 0; + else if (*pa < *pb) + return -1; + else + return 1; } void set_object_refs(struct object *obj, struct object_refs *refs) -- cgit v1.2.3 From 9754563ca9a99bc0fe233f43202af15704fbed4d Mon Sep 17 00:00:00 2001 From: Jason Riedy Date: Tue, 6 Dec 2005 14:21:52 -0800 Subject: Use printf rather than echo -n. On AIX, there is no -n option to the system's echo. Instead, it needs the '\c' control character. We could replace echo -n "foo" with echo -e "foo\c" but printf is recommended by most man pages. Tested on AIX 5.3, Solaris 8, and Debian. [jc: futureproofed two instances that uses variable with '%s' so later feeding different messages would not break things too easily; others are emitting literal so whoever changes the literal ought to notice more easily so they are safe.] Signed-off-by: E. Jason Riedy Signed-off-by: Junio C Hamano --- git-am.sh | 2 +- git-applypatch.sh | 2 +- git-bisect.sh | 2 +- git-status.sh | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/git-am.sh b/git-am.sh index 660b3a4b61..6ed527c7a9 100755 --- a/git-am.sh +++ b/git-am.sh @@ -312,7 +312,7 @@ do echo "--------------------------" cat "$dotest/final-commit" echo "--------------------------" - echo -n "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all " + printf "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all " read reply case "$reply" in [yY]*) action=yes ;; diff --git a/git-applypatch.sh b/git-applypatch.sh index 4c577eb835..a112e1a504 100755 --- a/git-applypatch.sh +++ b/git-applypatch.sh @@ -83,7 +83,7 @@ while [ "$interactive" = yes ]; do echo "--------------------------" cat "$final" echo "--------------------------" - echo -n "Apply? [y]es/[n]o/[e]dit/[a]ccept all " + printf "Apply? [y]es/[n]o/[e]dit/[a]ccept all " read reply case "$reply" in y|Y) interactive=no;; diff --git a/git-bisect.sh b/git-bisect.sh index 68838f3fad..05dae8ad13 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -67,7 +67,7 @@ bisect_start() { rm -rf "$GIT_DIR/refs/bisect/" mkdir "$GIT_DIR/refs/bisect" { - echo -n "git-bisect start" + printf "git-bisect start" sq "$@" } >"$GIT_DIR/BISECT_LOG" sq "$@" >"$GIT_DIR/BISECT_NAMES" diff --git a/git-status.sh b/git-status.sh index b90ffc198d..2dda0c505c 100755 --- a/git-status.sh +++ b/git-status.sh @@ -13,7 +13,7 @@ report () { trailer="" while read status name newname do - echo -n "$header" + printf '%s' "$header" header="" trailer="# " @@ -27,7 +27,7 @@ report () { U ) echo "# unmerged: $name";; esac done - echo -n "$trailer" + printf '%s' "$trailer" [ "$header" ] } -- cgit v1.2.3 From 3bd348aeea24709cd9be4b9d741f79b6014cd7e3 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 00:29:51 -0800 Subject: checkout-index: allow checking out from higher stages. The new option, --stage=, lets you copy out from an unmerged, higher stage. This is to help the new merge world order during a nontrivial merge. Signed-off-by: Junio C Hamano --- Documentation/git-checkout-index.txt | 6 +++- checkout-index.c | 61 +++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/Documentation/git-checkout-index.txt b/Documentation/git-checkout-index.txt index 97eef22ccd..9f32c65aab 100644 --- a/Documentation/git-checkout-index.txt +++ b/Documentation/git-checkout-index.txt @@ -9,7 +9,7 @@ git-checkout-index - Copy files from the index to the working directory SYNOPSIS -------- 'git-checkout-index' [-u] [-q] [-a] [-f] [-n] [--prefix=] - [--] ... + [--stage=] [--] ... DESCRIPTION ----------- @@ -40,6 +40,10 @@ OPTIONS When creating files, prepend (usually a directory including a trailing /) +--stage=:: + Instead of checking out unmerged entries, copy out the + files from named stage. must be between 1 and 3. + --:: Do not interpret any more arguments as options. diff --git a/checkout-index.c b/checkout-index.c index f1e716d412..1e1c9727e0 100644 --- a/checkout-index.c +++ b/checkout-index.c @@ -36,6 +36,7 @@ static const char *prefix; static int prefix_length; +static int checkout_stage; /* default to checkout stage0 */ static struct checkout state = { .base_dir = "", @@ -48,20 +49,36 @@ static struct checkout state = { static int checkout_file(const char *name) { - int pos = cache_name_pos(name, strlen(name)); - if (pos < 0) { - if (!state.quiet) { - pos = -pos - 1; - fprintf(stderr, - "git-checkout-index: %s is %s.\n", - name, - (pos < active_nr && - !strcmp(active_cache[pos]->name, name)) ? - "unmerged" : "not in the cache"); - } - return -1; + int namelen = strlen(name); + int pos = cache_name_pos(name, namelen); + int has_same_name = 0; + + if (pos < 0) + pos = -pos - 1; + + while (pos < active_nr) { + struct cache_entry *ce = active_cache[pos]; + if (ce_namelen(ce) != namelen && + memcmp(ce->name, name, namelen)) + break; + has_same_name = 1; + if (checkout_stage == ce_stage(ce)) + return checkout_entry(ce, &state); + pos++; } - return checkout_entry(active_cache[pos], &state); + + if (!state.quiet) { + fprintf(stderr, "git-checkout-index: %s ", name); + if (!has_same_name) + fprintf(stderr, "is not in the cache"); + else if (checkout_stage) + fprintf(stderr, "does not exist at stage %d", + checkout_stage); + else + fprintf(stderr, "is unmerged"); + fputc('\n', stderr); + } + return -1; } static int checkout_all(void) @@ -70,11 +87,11 @@ static int checkout_all(void) for (i = 0; i < active_nr ; i++) { struct cache_entry *ce = active_cache[i]; - if (ce_stage(ce)) + if (ce_stage(ce) != checkout_stage) continue; if (prefix && *prefix && - ( ce_namelen(ce) <= prefix_length || - memcmp(prefix, ce->name, prefix_length) )) + (ce_namelen(ce) <= prefix_length || + memcmp(prefix, ce->name, prefix_length))) continue; if (checkout_entry(ce, &state) < 0) errs++; @@ -88,7 +105,7 @@ static int checkout_all(void) } static const char checkout_cache_usage[] = -"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--prefix=] [--] ..."; +"git-checkout-index [-u] [-q] [-a] [-f] [-n] [--stage=[123]] [--prefix=] [--] ..."; static struct cache_file cache_file; @@ -138,11 +155,19 @@ int main(int argc, char **argv) die("cannot open index.lock file."); continue; } - if (!memcmp(arg, "--prefix=", 9)) { + if (!strncmp(arg, "--prefix=", 9)) { state.base_dir = arg+9; state.base_dir_len = strlen(state.base_dir); continue; } + if (!strncmp(arg, "--stage=", 8)) { + int ch = arg[8]; + if ('1' <= ch && ch <= '3') + checkout_stage = arg[8] - '0'; + else + die("stage should be between 1 and 3"); + continue; + } if (arg[0] == '-') usage(checkout_cache_usage); break; -- cgit v1.2.3 From b539c5e8fbd36e38eb8f589e11aa5b136ddce753 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 00:50:33 -0800 Subject: git-merge-one: new merge world order. This does two things: - Use new --stage=2 option to create the working tree file with leading paths and correct permission bits using checkout-index, as before. - Make sure we do not confuse "merge" program when the file being merged has an unfortunate name, '-L'. Signed-off-by: Junio C Hamano --- git-merge-one-file.sh | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/git-merge-one-file.sh b/git-merge-one-file.sh index 88a5da99f6..7dee88a733 100755 --- a/git-merge-one-file.sh +++ b/git-merge-one-file.sh @@ -16,14 +16,6 @@ # been handled already by git-read-tree, but that one doesn't # do any merges that might change the tree layout. -verify_path() { - file="$1" - dir=`dirname "$file"` && - mkdir -p "$dir" && - rm -f -- "$file" && - : >"$file" -} - case "${1:-.}${2:-.}${3:-.}" in # # Deleted in both or deleted in one and unchanged in the other @@ -95,15 +87,16 @@ case "${1:-.}${2:-.}${3:-.}" in ;; esac - # Create the working tree file, with the correct permission bits. - # we can not rely on the fact that our tree has the path, because - # we allow the merge to be done in an unchecked-out working tree. - verify_path "$4" && - git-cat-file blob "$2" >"$4" && - case "$6" in *7??) chmod +x -- "$4" ;; esac && - merge "$4" "$orig" "$src2" + # Be careful for funny filename such as "-L" in "$4", which + # would confuse "merge" greatly. + src1=`git-unpack-file $2` + merge "$src1" "$orig" "$src2" ret=$? - rm -f -- "$orig" "$src2" + + # Create the working tree file, using "our tree" version from the + # index, and then store the result of the merge. + git-checkout-index -f --stage=2 -- "$4" && cat "$src1" >"$4" + rm -f -- "$orig" "$src1" "$src2" if [ "$6" != "$7" ]; then echo "ERROR: Permissions conflict: $5->$6,$7." -- cgit v1.2.3 From d23748a6af3e3db2b239090553f92c3a779b3578 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 01:45:38 -0800 Subject: update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano --- Documentation/git-update-index.txt | 57 +++++++++++++++++++++++++++++++++ update-index.c | 65 +++++++++++++++++++++++++++----------- 2 files changed, 104 insertions(+), 18 deletions(-) diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index e4678cd280..c74311dabd 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -136,6 +136,63 @@ in the database but the file isn't available locally. '--info-only' is useful when the file is available, but you do not wish to update the object database. + +Using --index-info +------------------ + +`--index-info` is a more powerful mechanism that lets you feed +multiple entry definitions from the standard input, and designed +specifically for scripts. It can take inputs of three formats: + + . mode SP sha1 TAB path ++ +The first format is what "git-apply --index-info" +reports, and used to reconstruct a partial tree +that is used for phony merge base tree when falling +back on 3-way merge. + + . mode SP type SP sha1 TAB path ++ +The second format is to stuff git-ls-tree output +into the index file. + + . mode SP sha1 SP stage TAB path ++ +This format is to put higher order stages into the +index file and matches git-ls-files --stage output. + +To place a higher stage entry to the index, the path should +first be removed by feeding a mode=0 entry for the path, and +then feeding necessary input lines in the third format. + +For example, starting with this index: + +------------ +$ git ls-files -s +100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz +------------ + +you can feed the following input to `--index-info`: + +------------ +$ git update-index --index-info +0 0000000000000000000000000000000000000000 frotz +100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz +100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz +------------ + +The first line of the input feeds 0 as the mode to remove the +path; the SHA1 does not matter as long as it is well formatted. +Then the second and third line feeds stage 1 and stage 2 entries +for that path. After the above, we would end up with this: + +------------ +$ git ls-files -s +100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz +100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz +------------ + + Examples -------- To update and refresh only the files already checked out: diff --git a/update-index.c b/update-index.c index 11b7f6a516..be87b99808 100644 --- a/update-index.c +++ b/update-index.c @@ -256,35 +256,30 @@ inside: } } -static int add_cacheinfo(const char *arg1, const char *arg2, const char *arg3) +static int add_cacheinfo(unsigned int mode, const unsigned char *sha1, + const char *path, int stage) { int size, len, option; - unsigned int mode; - unsigned char sha1[20]; struct cache_entry *ce; - if (sscanf(arg1, "%o", &mode) != 1) - return -1; - if (get_sha1_hex(arg2, sha1)) - return -1; - if (!verify_path(arg3)) + if (!verify_path(path)) return -1; - len = strlen(arg3); + len = strlen(path); size = cache_entry_size(len); ce = xmalloc(size); memset(ce, 0, size); memcpy(ce->sha1, sha1, 20); - memcpy(ce->name, arg3, len); - ce->ce_flags = htons(len); + memcpy(ce->name, path, len); + ce->ce_flags = create_ce_flags(len, stage); ce->ce_mode = create_ce_mode(mode); option = allow_add ? ADD_CACHE_OK_TO_ADD : 0; option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0; if (add_cache_entry(ce, option)) return error("%s: cannot add to the index - missing --add option?", - arg3); - report("add '%s'", arg3); + path); + report("add '%s'", path); return 0; } @@ -342,7 +337,24 @@ static void read_index_info(int line_termination) char *path_name; unsigned char sha1[20]; unsigned int mode; - + int stage; + + /* This reads lines formatted in one of three formats: + * + * (1) mode SP sha1 TAB path + * The first format is what "git-apply --index-info" + * reports, and used to reconstruct a partial tree + * that is used for phony merge base tree when falling + * back on 3-way merge. + * + * (2) mode SP type SP sha1 TAB path + * The second format is to stuff git-ls-tree output + * into the index file. + * + * (3) mode SP sha1 SP stage TAB path + * This format is to put higher order stages into the + * index file and matches git-ls-files --stage output. + */ read_line(&buf, stdin, line_termination); if (buf.eof) break; @@ -354,9 +366,19 @@ static void read_index_info(int line_termination) tab = strchr(ptr, '\t'); if (!tab || tab - ptr < 41) goto bad_line; + + if (tab[-2] == ' ' && '1' <= tab[-1] && tab[-1] <= '3') { + stage = tab[-1] - '0'; + ptr = tab + 1; /* point at the head of path */ + tab = tab - 2; /* point at tail of sha1 */ + } + else { + stage = 0; + ptr = tab + 1; /* point at the head of path */ + } + if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ') goto bad_line; - ptr = tab + 1; if (line_termination && ptr[0] == '"') path_name = unquote_c_style(ptr, NULL); @@ -382,7 +404,7 @@ static void read_index_info(int line_termination) * ptr[-41] is at the beginning of sha1 */ ptr[-42] = ptr[-1] = 0; - if (add_cacheinfo(buf.buf, ptr-41, path_name)) + if (add_cacheinfo(mode, sha1, path_name, stage)) die("git-update-index: unable to update %s", path_name); } @@ -449,10 +471,17 @@ int main(int argc, const char **argv) continue; } if (!strcmp(path, "--cacheinfo")) { + unsigned char sha1[20]; + unsigned int mode; + if (i+3 >= argc) die("git-update-index: --cacheinfo "); - if (add_cacheinfo(argv[i+1], argv[i+2], argv[i+3])) - die("git-update-index: --cacheinfo cannot add %s", argv[i+3]); + + if ((sscanf(argv[i+1], "%o", &mode) != 1) || + get_sha1_hex(argv[i+2], sha1) || + add_cacheinfo(mode, sha1, argv[i+3], 0)) + die("git-update-index: --cacheinfo" + " cannot add %s", argv[i+3]); i += 3; continue; } -- cgit v1.2.3 From fd8ccbec4f0161b14f804a454e68b29e24840ad3 Mon Sep 17 00:00:00 2001 From: Paul Mackerras Date: Wed, 7 Dec 2005 23:28:22 +1100 Subject: gitk: Work around Tcl's non-standard names for encodings This uses a table of encoding names and aliases distilled from http://www.iana.org/assignments/character-sets plus some heuristics to convert standard encoding names to ones that Tcl recognizes. Signed-off-by: Paul Mackerras --- gitk | 468 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 374 insertions(+), 94 deletions(-) diff --git a/gitk b/gitk index 2e94145021..f12b3ce209 100755 --- a/gitk +++ b/gitk @@ -34,7 +34,7 @@ proc parse_args {rargs} { proc start_rev_list {rlargs} { global startmsecs nextupdate ncmupdate - global commfd leftover gitencoding + global commfd leftover tclencoding set startmsecs [clock clicks -milliseconds] set nextupdate [expr {$startmsecs + 100}] @@ -47,7 +47,10 @@ proc start_rev_list {rlargs} { exit 1 } set leftover {} - fconfigure $commfd -blocking 0 -translation lf -encoding $gitencoding + fconfigure $commfd -blocking 0 -translation lf + if {$tclencoding != {}} { + fconfigure $commfd -encoding $tclencoding + } fileevent $commfd readable [list getcommitlines $commfd] . config -cursor watch settextcursor watch @@ -182,6 +185,96 @@ proc readcommit {id} { parsecommit $id $contents 0 {} } +proc updatecommits {rargs} { + global commitlisted commfd phase + global startmsecs nextupdate ncmupdate + global idtags idheads idotherrefs + global leftover + global parsed_args + global canv mainfont + global oldcommits commits + global parents nchildren children ncleft + + set old_args $parsed_args + parse_args $rargs + + if {$phase == "getcommits" || $phase == "incrdraw"} { + # havent read all the old commits, just start again from scratch + stopfindproc + set oldcommits {} + set commits {} + foreach v {children nchildren parents commitlisted commitinfo + selectedline matchinglines treediffs + mergefilelist currentid rowtextx} { + global $v + catch {unset $v} + } + readrefs + if {$phase == "incrdraw"} { + allcanvs delete all + $canv create text 3 3 -anchor nw -text "Reading commits..." \ + -font $mainfont -tags textitems + set phase getcommits + } + start_rev_list $parsed_args + return + } + + foreach id $old_args { + if {![regexp {^[0-9a-f]{40}$} $id]} continue + if {[info exists oldref($id)]} continue + set oldref($id) $id + lappend ignoreold "^$id" + } + foreach id $parsed_args { + if {![regexp {^[0-9a-f]{40}$} $id]} continue + if {[info exists ref($id)]} continue + set ref($id) $id + lappend ignorenew "^$id" + } + + foreach a $old_args { + if {![info exists ref($a)]} { + lappend ignorenew $a + } + } + + set phase updatecommits + set oldcommits $commits + set commits {} + set removed_commits [split [eval exec git-rev-list $ignorenew] "\n" ] + if {[llength $removed_commits] > 0} { + allcanvs delete all + foreach c $removed_commits { + set i [lsearch -exact $oldcommits $c] + if {$i >= 0} { + set oldcommits [lreplace $oldcommits $i $i] + unset commitlisted($c) + foreach p $parents($c) { + if {[info exists nchildren($p)]} { + set j [lsearch -exact $children($p) $c] + if {$j >= 0} { + set children($p) [lreplace $children($p) $j $j] + incr nchildren($p) -1 + } + } + } + } + } + set phase removecommits + } + + set args {} + foreach a $parsed_args { + if {![info exists oldref($a)]} { + lappend args $a + } + } + + readrefs + start_rev_list [concat $ignoreold $args] +} + proc updatechildren {id olds} { global children nchildren parents nparents ncleft @@ -3624,96 +3717,6 @@ proc rereadrefs {} { } } -proc updatecommits {rargs} { - global commitlisted commfd phase - global startmsecs nextupdate ncmupdate - global idtags idheads idotherrefs - global leftover - global parsed_args - global canv mainfont - global oldcommits commits - global parents nchildren children ncleft - - set old_args $parsed_args - parse_args $rargs - - if {$phase == "getcommits" || $phase == "incrdraw"} { - # havent read all the old commits, just start again from scratch - stopfindproc - set oldcommits {} - set commits {} - foreach v {children nchildren parents commitlisted commitinfo - selectedline matchinglines treediffs - mergefilelist currentid rowtextx} { - global $v - catch {unset $v} - } - readrefs - if {$phase == "incrdraw"} { - allcanvs delete all - $canv create text 3 3 -anchor nw -text "Reading commits..." \ - -font $mainfont -tags textitems - set phase getcommits - } - start_rev_list $parsed_args - return - } - - foreach id $old_args { - if {![regexp {^[0-9a-f]{40}$} $id]} continue - if {[info exists oldref($id)]} continue - set oldref($id) $id - lappend ignoreold "^$id" - } - foreach id $parsed_args { - if {![regexp {^[0-9a-f]{40}$} $id]} continue - if {[info exists ref($id)]} continue - set ref($id) $id - lappend ignorenew "^$id" - } - - foreach a $old_args { - if {![info exists ref($a)]} { - lappend ignorenew $a - } - } - - set phase updatecommits - set oldcommits $commits - set commits {} - set removed_commits [split [eval exec git-rev-list $ignorenew] "\n" ] - if {[llength $removed_commits] > 0} { - allcanvs delete all - foreach c $removed_commits { - set i [lsearch -exact $oldcommits $c] - if {$i >= 0} { - set oldcommits [lreplace $oldcommits $i $i] - unset commitlisted($c) - foreach p $parents($c) { - if {[info exists nchildren($p)]} { - set j [lsearch -exact $children($p) $c] - if {$j >= 0} { - set children($p) [lreplace $children($p) $j $j] - incr nchildren($p) -1 - } - } - } - } - } - set phase removecommits - } - - set args {} - foreach a $parsed_args { - if {![info exists oldref($a)]} { - lappend args $a - } - } - - readrefs - start_rev_list [concat $ignoreold $args] -} - proc showtag {tag isnew} { global ctext cflist tagcontents tagids linknum @@ -3811,17 +3814,294 @@ proc formatdate {d} { return [clock format $d -format "%Y-%m-%d %H:%M:%S"] } +# This list of encoding names and aliases is distilled from +# http://www.iana.org/assignments/character-sets. +# Not all of them are supported by Tcl. +set encoding_aliases { + { ANSI_X3.4-1968 iso-ir-6 ANSI_X3.4-1986 ISO_646.irv:1991 ASCII + ISO646-US US-ASCII us IBM367 cp367 csASCII } + { ISO-10646-UTF-1 csISO10646UTF1 } + { ISO_646.basic:1983 ref csISO646basic1983 } + { INVARIANT csINVARIANT } + { ISO_646.irv:1983 iso-ir-2 irv csISO2IntlRefVersion } + { BS_4730 iso-ir-4 ISO646-GB gb uk csISO4UnitedKingdom } + { NATS-SEFI iso-ir-8-1 csNATSSEFI } + { NATS-SEFI-ADD iso-ir-8-2 csNATSSEFIADD } + { NATS-DANO iso-ir-9-1 csNATSDANO } + { NATS-DANO-ADD iso-ir-9-2 csNATSDANOADD } + { SEN_850200_B iso-ir-10 FI ISO646-FI ISO646-SE se csISO10Swedish } + { SEN_850200_C iso-ir-11 ISO646-SE2 se2 csISO11SwedishForNames } + { KS_C_5601-1987 iso-ir-149 KS_C_5601-1989 KSC_5601 korean csKSC56011987 } + { ISO-2022-KR csISO2022KR } + { EUC-KR csEUCKR } + { ISO-2022-JP csISO2022JP } + { ISO-2022-JP-2 csISO2022JP2 } + { JIS_C6220-1969-jp JIS_C6220-1969 iso-ir-13 katakana x0201-7 + csISO13JISC6220jp } + { JIS_C6220-1969-ro iso-ir-14 jp ISO646-JP csISO14JISC6220ro } + { IT iso-ir-15 ISO646-IT csISO15Italian } + { PT iso-ir-16 ISO646-PT csISO16Portuguese } + { ES iso-ir-17 ISO646-ES csISO17Spanish } + { greek7-old iso-ir-18 csISO18Greek7Old } + { latin-greek iso-ir-19 csISO19LatinGreek } + { DIN_66003 iso-ir-21 de ISO646-DE csISO21German } + { NF_Z_62-010_(1973) iso-ir-25 ISO646-FR1 csISO25French } + { Latin-greek-1 iso-ir-27 csISO27LatinGreek1 } + { ISO_5427 iso-ir-37 csISO5427Cyrillic } + { JIS_C6226-1978 iso-ir-42 csISO42JISC62261978 } + { BS_viewdata iso-ir-47 csISO47BSViewdata } + { INIS iso-ir-49 csISO49INIS } + { INIS-8 iso-ir-50 csISO50INIS8 } + { INIS-cyrillic iso-ir-51 csISO51INISCyrillic } + { ISO_5427:1981 iso-ir-54 ISO5427Cyrillic1981 } + { ISO_5428:1980 iso-ir-55 csISO5428Greek } + { GB_1988-80 iso-ir-57 cn ISO646-CN csISO57GB1988 } + { GB_2312-80 iso-ir-58 chinese csISO58GB231280 } + { NS_4551-1 iso-ir-60 ISO646-NO no csISO60DanishNorwegian + csISO60Norwegian1 } + { NS_4551-2 ISO646-NO2 iso-ir-61 no2 csISO61Norwegian2 } + { NF_Z_62-010 iso-ir-69 ISO646-FR fr csISO69French } + { videotex-suppl iso-ir-70 csISO70VideotexSupp1 } + { PT2 iso-ir-84 ISO646-PT2 csISO84Portuguese2 } + { ES2 iso-ir-85 ISO646-ES2 csISO85Spanish2 } + { MSZ_7795.3 iso-ir-86 ISO646-HU hu csISO86Hungarian } + { JIS_C6226-1983 iso-ir-87 x0208 JIS_X0208-1983 csISO87JISX0208 } + { greek7 iso-ir-88 csISO88Greek7 } + { ASMO_449 ISO_9036 arabic7 iso-ir-89 csISO89ASMO449 } + { iso-ir-90 csISO90 } + { JIS_C6229-1984-a iso-ir-91 jp-ocr-a csISO91JISC62291984a } + { JIS_C6229-1984-b iso-ir-92 ISO646-JP-OCR-B jp-ocr-b + csISO92JISC62991984b } + { JIS_C6229-1984-b-add iso-ir-93 jp-ocr-b-add csISO93JIS62291984badd } + { JIS_C6229-1984-hand iso-ir-94 jp-ocr-hand csISO94JIS62291984hand } + { JIS_C6229-1984-hand-add iso-ir-95 jp-ocr-hand-add + csISO95JIS62291984handadd } + { JIS_C6229-1984-kana iso-ir-96 csISO96JISC62291984kana } + { ISO_2033-1983 iso-ir-98 e13b csISO2033 } + { ANSI_X3.110-1983 iso-ir-99 CSA_T500-1983 NAPLPS csISO99NAPLPS } + { ISO_8859-1:1987 iso-ir-100 ISO_8859-1 ISO-8859-1 latin1 l1 IBM819 + CP819 csISOLatin1 } + { ISO_8859-2:1987 iso-ir-101 ISO_8859-2 ISO-8859-2 latin2 l2 csISOLatin2 } + { T.61-7bit iso-ir-102 csISO102T617bit } + { T.61-8bit T.61 iso-ir-103 csISO103T618bit } + { ISO_8859-3:1988 iso-ir-109 ISO_8859-3 ISO-8859-3 latin3 l3 csISOLatin3 } + { ISO_8859-4:1988 iso-ir-110 ISO_8859-4 ISO-8859-4 latin4 l4 csISOLatin4 } + { ECMA-cyrillic iso-ir-111 KOI8-E csISO111ECMACyrillic } + { CSA_Z243.4-1985-1 iso-ir-121 ISO646-CA csa7-1 ca csISO121Canadian1 } + { CSA_Z243.4-1985-2 iso-ir-122 ISO646-CA2 csa7-2 csISO122Canadian2 } + { CSA_Z243.4-1985-gr iso-ir-123 csISO123CSAZ24341985gr } + { ISO_8859-6:1987 iso-ir-127 ISO_8859-6 ISO-8859-6 ECMA-114 ASMO-708 + arabic csISOLatinArabic } + { ISO_8859-6-E csISO88596E ISO-8859-6-E } + { ISO_8859-6-I csISO88596I ISO-8859-6-I } + { ISO_8859-7:1987 iso-ir-126 ISO_8859-7 ISO-8859-7 ELOT_928 ECMA-118 + greek greek8 csISOLatinGreek } + { T.101-G2 iso-ir-128 csISO128T101G2 } + { ISO_8859-8:1988 iso-ir-138 ISO_8859-8 ISO-8859-8 hebrew + csISOLatinHebrew } + { ISO_8859-8-E csISO88598E ISO-8859-8-E } + { ISO_8859-8-I csISO88598I ISO-8859-8-I } + { CSN_369103 iso-ir-139 csISO139CSN369103 } + { JUS_I.B1.002 iso-ir-141 ISO646-YU js yu csISO141JUSIB1002 } + { ISO_6937-2-add iso-ir-142 csISOTextComm } + { IEC_P27-1 iso-ir-143 csISO143IECP271 } + { ISO_8859-5:1988 iso-ir-144 ISO_8859-5 ISO-8859-5 cyrillic + csISOLatinCyrillic } + { JUS_I.B1.003-serb iso-ir-146 serbian csISO146Serbian } + { JUS_I.B1.003-mac macedonian iso-ir-147 csISO147Macedonian } + { ISO_8859-9:1989 iso-ir-148 ISO_8859-9 ISO-8859-9 latin5 l5 csISOLatin5 } + { greek-ccitt iso-ir-150 csISO150 csISO150GreekCCITT } + { NC_NC00-10:81 cuba iso-ir-151 ISO646-CU csISO151Cuba } + { ISO_6937-2-25 iso-ir-152 csISO6937Add } + { GOST_19768-74 ST_SEV_358-88 iso-ir-153 csISO153GOST1976874 } + { ISO_8859-supp iso-ir-154 latin1-2-5 csISO8859Supp } + { ISO_10367-box iso-ir-155 csISO10367Box } + { ISO-8859-10 iso-ir-157 l6 ISO_8859-10:1992 csISOLatin6 latin6 } + { latin-lap lap iso-ir-158 csISO158Lap } + { JIS_X0212-1990 x0212 iso-ir-159 csISO159JISX02121990 } + { DS_2089 DS2089 ISO646-DK dk csISO646Danish } + { us-dk csUSDK } + { dk-us csDKUS } + { JIS_X0201 X0201 csHalfWidthKatakana } + { KSC5636 ISO646-KR csKSC5636 } + { ISO-10646-UCS-2 csUnicode } + { ISO-10646-UCS-4 csUCS4 } + { DEC-MCS dec csDECMCS } + { hp-roman8 roman8 r8 csHPRoman8 } + { macintosh mac csMacintosh } + { IBM037 cp037 ebcdic-cp-us ebcdic-cp-ca ebcdic-cp-wt ebcdic-cp-nl + csIBM037 } + { IBM038 EBCDIC-INT cp038 csIBM038 } + { IBM273 CP273 csIBM273 } + { IBM274 EBCDIC-BE CP274 csIBM274 } + { IBM275 EBCDIC-BR cp275 csIBM275 } + { IBM277 EBCDIC-CP-DK EBCDIC-CP-NO csIBM277 } + { IBM278 CP278 ebcdic-cp-fi ebcdic-cp-se csIBM278 } + { IBM280 CP280 ebcdic-cp-it csIBM280 } + { IBM281 EBCDIC-JP-E cp281 csIBM281 } + { IBM284 CP284 ebcdic-cp-es csIBM284 } + { IBM285 CP285 ebcdic-cp-gb csIBM285 } + { IBM290 cp290 EBCDIC-JP-kana csIBM290 } + { IBM297 cp297 ebcdic-cp-fr csIBM297 } + { IBM420 cp420 ebcdic-cp-ar1 csIBM420 } + { IBM423 cp423 ebcdic-cp-gr csIBM423 } + { IBM424 cp424 ebcdic-cp-he csIBM424 } + { IBM437 cp437 437 csPC8CodePage437 } + { IBM500 CP500 ebcdic-cp-be ebcdic-cp-ch csIBM500 } + { IBM775 cp775 csPC775Baltic } + { IBM850 cp850 850 csPC850Multilingual } + { IBM851 cp851 851 csIBM851 } + { IBM852 cp852 852 csPCp852 } + { IBM855 cp855 855 csIBM855 } + { IBM857 cp857 857 csIBM857 } + { IBM860 cp860 860 csIBM860 } + { IBM861 cp861 861 cp-is csIBM861 } + { IBM862 cp862 862 csPC862LatinHebrew } + { IBM863 cp863 863 csIBM863 } + { IBM864 cp864 csIBM864 } + { IBM865 cp865 865 csIBM865 } + { IBM866 cp866 866 csIBM866 } + { IBM868 CP868 cp-ar csIBM868 } + { IBM869 cp869 869 cp-gr csIBM869 } + { IBM870 CP870 ebcdic-cp-roece ebcdic-cp-yu csIBM870 } + { IBM871 CP871 ebcdic-cp-is csIBM871 } + { IBM880 cp880 EBCDIC-Cyrillic csIBM880 } + { IBM891 cp891 csIBM891 } + { IBM903 cp903 csIBM903 } + { IBM904 cp904 904 csIBBM904 } + { IBM905 CP905 ebcdic-cp-tr csIBM905 } + { IBM918 CP918 ebcdic-cp-ar2 csIBM918 } + { IBM1026 CP1026 csIBM1026 } + { EBCDIC-AT-DE csIBMEBCDICATDE } + { EBCDIC-AT-DE-A csEBCDICATDEA } + { EBCDIC-CA-FR csEBCDICCAFR } + { EBCDIC-DK-NO csEBCDICDKNO } + { EBCDIC-DK-NO-A csEBCDICDKNOA } + { EBCDIC-FI-SE csEBCDICFISE } + { EBCDIC-FI-SE-A csEBCDICFISEA } + { EBCDIC-FR csEBCDICFR } + { EBCDIC-IT csEBCDICIT } + { EBCDIC-PT csEBCDICPT } + { EBCDIC-ES csEBCDICES } + { EBCDIC-ES-A csEBCDICESA } + { EBCDIC-ES-S csEBCDICESS } + { EBCDIC-UK csEBCDICUK } + { EBCDIC-US csEBCDICUS } + { UNKNOWN-8BIT csUnknown8BiT } + { MNEMONIC csMnemonic } + { MNEM csMnem } + { VISCII csVISCII } + { VIQR csVIQR } + { KOI8-R csKOI8R } + { IBM00858 CCSID00858 CP00858 PC-Multilingual-850+euro } + { IBM00924 CCSID00924 CP00924 ebcdic-Latin9--euro } + { IBM01140 CCSID01140 CP01140 ebcdic-us-37+euro } + { IBM01141 CCSID01141 CP01141 ebcdic-de-273+euro } + { IBM01142 CCSID01142 CP01142 ebcdic-dk-277+euro ebcdic-no-277+euro } + { IBM01143 CCSID01143 CP01143 ebcdic-fi-278+euro ebcdic-se-278+euro } + { IBM01144 CCSID01144 CP01144 ebcdic-it-280+euro } + { IBM01145 CCSID01145 CP01145 ebcdic-es-284+euro } + { IBM01146 CCSID01146 CP01146 ebcdic-gb-285+euro } + { IBM01147 CCSID01147 CP01147 ebcdic-fr-297+euro } + { IBM01148 CCSID01148 CP01148 ebcdic-international-500+euro } + { IBM01149 CCSID01149 CP01149 ebcdic-is-871+euro } + { IBM1047 IBM-1047 } + { PTCP154 csPTCP154 PT154 CP154 Cyrillic-Asian } + { Amiga-1251 Ami1251 Amiga1251 Ami-1251 } + { UNICODE-1-1 csUnicode11 } + { CESU-8 csCESU-8 } + { BOCU-1 csBOCU-1 } + { UNICODE-1-1-UTF-7 csUnicode11UTF7 } + { ISO-8859-14 iso-ir-199 ISO_8859-14:1998 ISO_8859-14 latin8 iso-celtic + l8 } + { ISO-8859-15 ISO_8859-15 Latin-9 } + { ISO-8859-16 iso-ir-226 ISO_8859-16:2001 ISO_8859-16 latin10 l10 } + { GBK CP936 MS936 windows-936 } + { JIS_Encoding csJISEncoding } + { Shift_JIS MS_Kanji csShiftJIS } + { Extended_UNIX_Code_Packed_Format_for_Japanese csEUCPkdFmtJapanese + EUC-JP } + { Extended_UNIX_Code_Fixed_Width_for_Japanese csEUCFixWidJapanese } + { ISO-10646-UCS-Basic csUnicodeASCII } + { ISO-10646-Unicode-Latin1 csUnicodeLatin1 ISO-10646 } + { ISO-Unicode-IBM-1261 csUnicodeIBM1261 } + { ISO-Unicode-IBM-1268 csUnicodeIBM1268 } + { ISO-Unicode-IBM-1276 csUnicodeIBM1276 } + { ISO-Unicode-IBM-1264 csUnicodeIBM1264 } + { ISO-Unicode-IBM-1265 csUnicodeIBM1265 } + { ISO-8859-1-Windows-3.0-Latin-1 csWindows30Latin1 } + { ISO-8859-1-Windows-3.1-Latin-1 csWindows31Latin1 } + { ISO-8859-2-Windows-Latin-2 csWindows31Latin2 } + { ISO-8859-9-Windows-Latin-5 csWindows31Latin5 } + { Adobe-Standard-Encoding csAdobeStandardEncoding } + { Ventura-US csVenturaUS } + { Ventura-International csVenturaInternational } + { PC8-Danish-Norwegian csPC8DanishNorwegian } + { PC8-Turkish csPC8Turkish } + { IBM-Symbols csIBMSymbols } + { IBM-Thai csIBMThai } + { HP-Legal csHPLegal } + { HP-Pi-font csHPPiFont } + { HP-Math8 csHPMath8 } + { Adobe-Symbol-Encoding csHPPSMath } + { HP-DeskTop csHPDesktop } + { Ventura-Math csVenturaMath } + { Microsoft-Publishing csMicrosoftPublishing } + { Windows-31J csWindows31J } + { GB2312 csGB2312 } + { Big5 csBig5 } +} + +proc tcl_encoding {enc} { + global encoding_aliases + set names [encoding names] + set lcnames [string tolower $names] + set enc [string tolower $enc] + set i [lsearch -exact $lcnames $enc] + if {$i < 0} { + # look for "isonnn" instead of "iso-nnn" or "iso_nnn" + if {[regsub {^iso[-_]} $enc iso encx]} { + set i [lsearch -exact $lcnames $encx] + } + } + if {$i < 0} { + foreach l $encoding_aliases { + set ll [string tolower $l] + if {[lsearch -exact $ll $enc] < 0} continue + # look through the aliases for one that tcl knows about + foreach e $ll { + set i [lsearch -exact $lcnames $e] + if {$i < 0} { + if {[regsub {^iso[-_]} $e iso ex]} { + set i [lsearch -exact $lcnames $ex] + } + } + if {$i >= 0} break + } + break + } + } + if {$i >= 0} { + return [lindex $names $i] + } + return {} +} + # defaults... set datemode 0 set diffopts "-U 5 -p" set wrcomcmd "git-diff-tree --stdin -p --pretty" -set gitencoding "" +set gitencoding {} catch { set gitencoding [exec git-repo-config --get i18n.commitencoding] } if {$gitencoding == ""} { - set gitencoding "utf-8" + set gitencoding "utf-8" +} +set tclencoding [tcl_encoding $gitencoding] +if {$tclencoding == {}} { + puts stderr "Warning: encoding $gitencoding is not supported by Tcl/Tk" } set mainfont {Helvetica 9} -- cgit v1.2.3 From 2fa090b6c145db9f6219a037c773fb63fe727019 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 16:05:21 -0800 Subject: Documentation: git.html/git.7 Finish each sentence with a full stop. Instead of saying 'directory index' 'directory cache' etc, consistently say 'index'. Signed-off-by: Junio C Hamano --- Documentation/git.txt | 174 +++++++++++++++++++++++++++----------------------- README | 17 +++-- 2 files changed, 104 insertions(+), 87 deletions(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index a518249863..fc11516deb 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -38,10 +38,13 @@ CORE GIT COMMANDS Before reading this cover to cover, you may want to take a look at the link:tutorial.html[tutorial] document. -The <> section below contains much useful definition and -clarification info - read that first. And of the commands, I suggest -reading gitlink:git-update-index[1] and -gitlink:git-read-tree[1] first - I wish I had! +The <> section below contains much useful definition +and clarification info - read that first. After that, if you +are interested in using git to manage (version control) +projects, read on commands listed in Porcelain-ish commands +section next. On the other hand, if you are writing your own +Porcelain, I suggest reading gitlink:git-update-index[1] and +gitlink:git-read-tree[1] first. If you are migrating from CVS, link:cvs-migration.html[cvs migration] document may be helpful after you finish the tutorial. @@ -54,13 +57,13 @@ link:howto-index.html[howto] documents. David Greaves 08/05/05 -Updated by Junio C Hamano on 2005-05-05 to -reflect recent changes. +Updated by Junio C Hamano on 2005-05-05 and +further on 2005-12-07 to reflect recent changes. Commands Overview ----------------- The git commands can helpfully be split into those that manipulate -the repository, the index and the working fileset, those that +the repository, the index and the files in the working tree, those that interrogate and compare them, and those that moves objects and references between repositories. @@ -79,25 +82,26 @@ gitlink:git-apply[1]:: applies it to the working tree. gitlink:git-checkout-index[1]:: - Copy files from the index to the working directory + Copy files from the index to the working tree. gitlink:git-commit-tree[1]:: - Creates a new commit object + Creates a new commit object. gitlink:git-hash-object[1]:: Computes the object ID from a file. gitlink:git-index-pack[1]:: - Build pack index file for an existing packed archive. + Build pack idx file for an existing packed archive. gitlink:git-init-db[1]:: - Creates an empty git object database + Creates an empty git object database, or reinitialize an + existing one. gitlink:git-merge-index[1]:: - Runs a merge for files needing merging + Runs a merge for files needing merging. gitlink:git-mktag[1]:: - Creates a tag object + Creates a tag object. gitlink:git-pack-objects[1]:: Creates a packed archive of objects. @@ -106,7 +110,7 @@ gitlink:git-prune-packed[1]:: Remove extra objects that are already in pack files. gitlink:git-read-tree[1]:: - Reads tree information into the directory index + Reads tree information into the index. gitlink:git-repo-config[1]:: Get and set options in .git/config. @@ -115,65 +119,65 @@ gitlink:git-unpack-objects[1]:: Unpacks objects out of a packed archive. gitlink:git-update-index[1]:: - Modifies the index or directory cache + Registers files in the working tree to the index. gitlink:git-write-tree[1]:: - Creates a tree from the current index + Creates a tree from the index. Interrogation commands ~~~~~~~~~~~~~~~~~~~~~~ gitlink:git-cat-file[1]:: - Provide content or type information for repository objects + Provide content or type/size information for repository objects. gitlink:git-diff-index[1]:: - Compares content and mode of blobs between the index and repository + Compares content and mode of blobs between the index and repository. gitlink:git-diff-files[1]:: - Compares files in the working tree and the index + Compares files in the working tree and the index. gitlink:git-diff-stages[1]:: - Compares two "merge stages" in the index file. + Compares two "merge stages" in the index. gitlink:git-diff-tree[1]:: - Compares the content and mode of blobs found via two tree objects + Compares the content and mode of blobs found via two tree objects. gitlink:git-fsck-objects[1]:: - Verifies the connectivity and validity of the objects in the database + Verifies the connectivity and validity of the objects in the database. gitlink:git-ls-files[1]:: - Information about files in the index/working directory + Information about files in the index and the working tree. gitlink:git-ls-tree[1]:: - Displays a tree object in human readable form + Displays a tree object in human readable form. gitlink:git-merge-base[1]:: - Finds as good a common ancestor as possible for a merge + Finds as good common ancestors as possible for a merge. gitlink:git-name-rev[1]:: - Find symbolic names for given revs + Find symbolic names for given revs. gitlink:git-rev-list[1]:: - Lists commit objects in reverse chronological order + Lists commit objects in reverse chronological order. gitlink:git-show-index[1]:: Displays contents of a pack idx file. gitlink:git-tar-tree[1]:: - Creates a tar archive of the files in the named tree + Creates a tar archive of the files in the named tree object. gitlink:git-unpack-file[1]:: - Creates a temporary file with a blob's contents + Creates a temporary file with a blob's contents. gitlink:git-var[1]:: - Displays a git logical variable + Displays a git logical variable. gitlink:git-verify-pack[1]:: - Validates packed git archive files + Validates packed git archive files. -The interrogate commands may create files - and you can force them to -touch the working file set - but in general they don't +In general, the interrogate commands do not touch the files in +the working tree. Synching repositories @@ -181,19 +185,24 @@ Synching repositories gitlink:git-clone-pack[1]:: Clones a repository into the current repository (engine - for ssh and local transport) + for ssh and local transport). gitlink:git-fetch-pack[1]:: - Updates from a remote repository. + Updates from a remote repository (engine for ssh and + local transport). gitlink:git-http-fetch[1]:: - Downloads a remote git repository via HTTP + Downloads a remote git repository via HTTP by walking + commit chain. gitlink:git-local-fetch[1]:: - Duplicates another git repository on a local system + Duplicates another git repository on a local system by + walking commit chain. gitlink:git-peek-remote[1]:: - Lists references on a remote repository using upload-pack protocol. + Lists references on a remote repository using + upload-pack protocol (engine for ssh and local + transport). gitlink:git-receive-pack[1]:: Invoked by 'git-send-pack' to receive what is pushed to it. @@ -205,10 +214,11 @@ gitlink:git-shell[1]:: Restricted shell for GIT-only SSH access. gitlink:git-ssh-fetch[1]:: - Pulls from a remote repository over ssh connection + Pulls from a remote repository over ssh connection by + walking commit chain. gitlink:git-ssh-upload[1]:: - Helper "server-side" program used by git-ssh-fetch + Helper "server-side" program used by git-ssh-fetch. gitlink:git-update-server-info[1]:: Updates auxiliary information on a dumb server to help @@ -223,16 +233,16 @@ Porcelain-ish Commands ---------------------- gitlink:git-add[1]:: - Add paths to the index file. + Add paths to the index. gitlink:git-am[1]:: Apply patches from a mailbox, but cooler. gitlink:git-applymbox[1]:: - Apply patches from a mailbox. + Apply patches from a mailbox, original version by Linus. gitlink:git-bisect[1]:: - Find the change that introduced a bug. + Find the change that introduced a bug by binary search. gitlink:git-branch[1]:: Create and Show branches. @@ -259,7 +269,7 @@ gitlink:git-format-patch[1]:: Prepare patches for e-mail submission. gitlink:git-grep[1]:: - Print lines matching a pattern + Print lines matching a pattern. gitlink:git-log[1]:: Shows commit logs. @@ -283,7 +293,7 @@ gitlink:git-push[1]:: Update remote refs along with associated objects. gitlink:git-rebase[1]:: - Rebase local commits to new upstream head. + Rebase local commits to the updated upstream head. gitlink:git-repack[1]:: Pack unpacked objects in a repository. @@ -324,7 +334,7 @@ gitlink:git-archimport[1]:: Import an arch repository into git. gitlink:git-convert-objects[1]:: - Converts old-style git repository + Converts old-style git repository. gitlink:git-cvsimport[1]:: Salvage your data out of another SCM people love to hate. @@ -333,10 +343,10 @@ gitlink:git-lost-found[1]:: Recover lost refs that luckily have not yet been pruned. gitlink:git-merge-one-file[1]:: - The standard helper program to use with "git-merge-index" + The standard helper program to use with `git-merge-index`. gitlink:git-prune[1]:: - Prunes all unreachable objects from the object database + Prunes all unreachable objects from the object database. gitlink:git-relink[1]:: Hardlink common objects in local repositories. @@ -348,10 +358,10 @@ gitlink:git-sh-setup[1]:: Common git shell script setup code. gitlink:git-symbolic-ref[1]:: - Read and modify symbolic refs + Read and modify symbolic refs. gitlink:git-tag[1]:: - An example script to create a tag object signed with GPG + An example script to create a tag object signed with GPG. gitlink:git-update-ref[1]:: Update the object name stored in a ref safely. @@ -375,16 +385,19 @@ gitlink:git-get-tar-commit-id[1]:: Extract commit ID from an archive created using git-tar-tree. gitlink:git-mailinfo[1]:: - Extracts patch from a single e-mail message. + Extracts patch and authorship information from a single + e-mail message, optionally transliterating the commit + message into utf-8. gitlink:git-mailsplit[1]:: - git-mailsplit. + A stupid program to split UNIX mbox format mailbox into + individual pieces of e-mail. gitlink:git-patch-id[1]:: Compute unique ID for a patch. gitlink:git-parse-remote[1]:: - Routines to help parsing $GIT_DIR/remotes/ + Routines to help parsing `$GIT_DIR/remotes/` files. gitlink:git-request-pull[1]:: git-request-pull. @@ -406,22 +419,20 @@ Commands not yet documented --------------------------- gitlink:gitk[1]:: - gitk. + The gitk repository browser. Configuration Mechanism ----------------------- -Starting from 0.99.9 (actually mid 0.99.8.GIT), .git/config file +Starting from 0.99.9 (actually mid 0.99.8.GIT), `.git/config` file is used to hold per-repository configuration options. It is a simple text file modelled after `.ini` format familiar to some people. Here is an example: ------------ # -# This is the config file, and -# a '#' or ';' character indicates -# a comment +# A '#' or ';' character indicates a comment. # ; core variables @@ -443,30 +454,30 @@ their operation accordingly. Identifier Terminology ---------------------- :: - Indicates the sha1 identifier for any type of object + Indicates the object name for any type of object. :: - Indicates a blob object sha1 identifier + Indicates a blob object name. :: - Indicates a tree object sha1 identifier + Indicates a tree object name. :: - Indicates a commit object sha1 identifier + Indicates a commit object name. :: - Indicates a tree, commit or tag object sha1 identifier. A + Indicates a tree, commit or tag object name. A command that takes a argument ultimately wants to operate on a object but automatically dereferences and objects that point at a . :: Indicates that an object type is required. - Currently one of: blob/tree/commit/tag + Currently one of: `blob`, `tree`, `commit`, or `tag`. :: - Indicates a filename - always relative to the root of - the tree structure GIT_INDEX_FILE describes. + Indicates a filename - almost always relative to the + root of the tree structure `GIT_INDEX_FILE` describes. Symbolic Identifiers -------------------- @@ -474,17 +485,20 @@ Any git command accepting any can also use the following symbolic notation: HEAD:: - indicates the head of the repository (ie the contents of - `$GIT_DIR/HEAD`) + indicates the head of the current branch (i.e. the + contents of `$GIT_DIR/HEAD`). + :: - a valid tag 'name'+ - (ie the contents of `$GIT_DIR/refs/tags/`) + a valid tag 'name' + (i.e. the contents of `$GIT_DIR/refs/tags/`). + :: - a valid head 'name'+ - (ie the contents of `$GIT_DIR/refs/heads/`) + a valid head 'name' + (i.e. the contents of `$GIT_DIR/refs/heads/`). + :: - a valid snapshot 'name'+ - (ie the contents of `$GIT_DIR/refs/snap/`) + a valid snapshot 'name' + (i.e. the contents of `$GIT_DIR/refs/snap/`). File/Directory Structure @@ -493,7 +507,7 @@ File/Directory Structure Please see link:repository-layout.html[repository layout] document. Higher level SCMs may provide and manage additional information in the -GIT_DIR. +`$GIT_DIR`. Terminology @@ -509,7 +523,7 @@ The git Repository ~~~~~~~~~~~~~~~~~~ These environment variables apply to 'all' core git commands. Nb: it is worth noting that they may be used/overridden by SCMS sitting above -git so take care if using Cogito etc +git so take care if using Cogito etc. 'GIT_INDEX_FILE':: This environment allows the specification of an alternate @@ -530,9 +544,9 @@ git so take care if using Cogito etc written to these directories. 'GIT_DIR':: - If the 'GIT_DIR' environment variable is set then it specifies - a path to use instead of `./.git` for the base of the - repository. + If the 'GIT_DIR' environment variable is set then it + specifies a path to use instead of the default `.git` + for the base of the repository. git Commits ~~~~~~~~~~~ @@ -559,7 +573,7 @@ include::../README[] Authors ------- git's founding father is Linus Torvalds . - The current git nurse is Junio C. Hamano . + The current git nurse is Junio C Hamano . The git potty was written by Andres Ericsson . General upbringing is handled by the git-list . diff --git a/README b/README index 36fef6ec04..cee7e435d7 100644 --- a/README +++ b/README @@ -35,7 +35,7 @@ the object (i.e. how it is used, and how it can refer to other objects). There are currently four different object types: "blob", "tree", "commit" and "tag". -A "blob" object cannot refer to any other object, and is, like the tag +A "blob" object cannot refer to any other object, and is, like the type implies, a pure storage object containing some user data. It is used to actually store the file data, i.e. a blob object is associated with some particular version of some file. @@ -64,7 +64,7 @@ symbolic name (of course!) and, optionally, a signature. Regardless of object type, all objects share the following characteristics: they are all deflated with zlib, and have a header -that not only specifies their tag, but also provides size information +that not only specifies their type, but also provides size information about the data in the object. It's worth noting that the SHA1 hash that is used to name the object is the hash of the original data plus this header, so `sha1sum` 'file' does not match the object name @@ -76,7 +76,7 @@ As a result, the general consistency of an object can always be tested independently of the contents or the type of the object: all objects can be validated by verifying that (a) their hashes match the content of the file and (b) the object successfully inflates to a stream of bytes that -forms a sequence of + + + + + + . The structured objects can further have their structure and @@ -297,7 +297,7 @@ will not normally add totally new entries or remove old entries, i.e. it will normally just update existing cache entries. To tell git that yes, you really do realize that certain files no -longer exist in the archive, or that new files should be added, you +longer exist, or that new files should be added, you should use the `--remove` and `--add` flags respectively. NOTE! A `--remove` flag does 'not' mean that subsequent filenames will @@ -515,8 +515,11 @@ index file, and you can just write the result out with Historical note. We did not have `-u` facility when this section was first written, so we used to warn that the merge is done in the index file, not in your -working directory, and your working directory will no longer match your -index. +working tree, and your working tree will not match your +index after this step. +This is no longer true. The above command, thanks to `-u` +option, updates your working tree with the merge results for +paths that have been trivially merged. 8) Merging multiple trees, continued @@ -579,7 +582,7 @@ The above is the description of a git merge at the lowest level, to help you understand what conceptually happens under the hood. In practice, nobody, not even git itself, uses three `git-cat-file` for this. There is `git-merge-index` program that extracts the -stages to temporary files and calls a `merge` script on it +stages to temporary files and calls a "merge" script on it: git-merge-index git-merge-one-file hello.c -- cgit v1.2.3 From 12bd7e78ee138e3ceefa5442db224c8288204b64 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 16:16:04 -0800 Subject: Documentation(glossary): minor formatting clean-ups. Signed-off-by: Junio C Hamano --- Documentation/glossary.txt | 12 ++++++------ Documentation/sort_glossary.pl | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index 07df6b48be..520f4c50fc 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -20,7 +20,7 @@ hash:: object database:: Stores a set of "objects", and an individial object is identified - by its object name. The object usually live in $GIT_DIR/objects/. + by its object name. The objects usually live in `$GIT_DIR/objects/`. blob object:: Untyped object, e.g. the contents of a file. @@ -109,15 +109,15 @@ head:: branch:: A non-cyclical graph of revisions, i.e. the complete history of a particular revision, which is called the branch head. The - branch heads are stored in $GIT_DIR/refs/heads/. + branch heads are stored in `$GIT_DIR/refs/heads/`. ref:: A 40-byte hex representation of a SHA1 pointing to a particular - object. These may be stored in $GIT_DIR/refs/. + object. These may be stored in `$GIT_DIR/refs/`. head ref:: A ref pointing to a head. Often, this is abbreviated to "head". - Head refs are stored in $GIT_DIR/refs/heads/. + Head refs are stored in `$GIT_DIR/refs/heads/`. tree-ish:: A ref pointing to either a commit object, a tree object, or a @@ -125,7 +125,7 @@ tree-ish:: ent:: Favorite synonym to "tree-ish" by some total geeks. See - http://en.wikipedia.org/wiki/Ent_(Middle-earth) for an in-depth + `http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth explanation. tag object:: @@ -137,7 +137,7 @@ tag object:: tag:: A ref pointing to a tag or commit object. In contrast to a head, a tag is not changed by a commit. Tags (not tag objects) are - stored in $GIT_DIR/refs/tags/. A git tag has nothing to do with + stored in `$GIT_DIR/refs/tags/`. A git tag has nothing to do with a Lisp tag (which is called object type in git's context). A tag is most typically used to mark a particular point in the commit ancestry chain. diff --git a/Documentation/sort_glossary.pl b/Documentation/sort_glossary.pl index babbea0415..e57dc78e0e 100644 --- a/Documentation/sort_glossary.pl +++ b/Documentation/sort_glossary.pl @@ -42,7 +42,6 @@ sub no_spaces ($) { print 'GIT Glossary ============ -Aug 2005 This list is sorted alphabetically: -- cgit v1.2.3 From 6bad1902f52c861e5e0adfc479987ff84b22dafe Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 16:26:49 -0800 Subject: Documentation(cvs-migration): minor cleanups. Signed-off-by: Junio C Hamano --- Documentation/cvs-migration.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/cvs-migration.txt b/Documentation/cvs-migration.txt index 57436f0078..dc9387b697 100644 --- a/Documentation/cvs-migration.txt +++ b/Documentation/cvs-migration.txt @@ -187,7 +187,8 @@ you would use git-rev-list and git-diff-tree like this: We have already talked about the "\--stdin" form of git-diff-tree command that reads the list of commits and compares each commit -with its parents. The git-whatchanged command internally runs +with its parents (otherwise you should go back and read the tutorial). +The git-whatchanged command internally runs the equivalent of the above command, and can be used like this: $ git-whatchanged -p -S'if (frotz) { -- cgit v1.2.3 From 361c06d8f5777c1037ad5c0e4d58f44cda4a5044 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 16:44:12 -0800 Subject: Documentation(tutorial): adjust merge example to the new merge world order. Signed-off-by: Junio C Hamano --- Documentation/tutorial.txt | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index db0bf3e527..0827056e1c 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1282,26 +1282,27 @@ fatal: merge program failed `git-merge-one-file` script is called with parameters to describe those three versions, and is responsible to leave the -merge results in the working tree and register it in the index -file. It is a fairly straightforward shell script, and -eventually calls `merge` program from RCS suite to perform the +merge results in the working tree. +It is a fairly straightforward shell script, and +eventually calls `merge` program from RCS suite to perform a file-level 3-way merge. In this case, `merge` detects conflicts, and the merge result with conflict marks is left in -the working tree, while the index file is updated with the -version from the current branch (this is to make `git diff` -useful after this step). This can be seen if you run `ls-files +the working tree.. This can be seen if you run `ls-files --stage` again at this point: ------------ $ git-ls-files --stage 100644 7f8b141b65fdcee47321e399a2598a235a032422 0 example -100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 0 hello +100644 263414f423d0e4d70dae8fe53fa34614ff3e2860 1 hello +100644 06fa6a24256dc7e560efa5687fa84b51f0263c3a 2 hello +100644 cc44c73eb783565da5831b4d820c962954019b69 3 hello ------------ -As you can see, there is no unmerged paths in the index file. This is the state of the index file and the working file after `git merge` returns control back to you, leaving the conflicting -merge for you to resolve. +merge for you to resolve. Notice that the path `hello` is still +unmerged, and what you see with `git diff` at this point is +differences since stage 2 (i.e. your version). Publishing your work @@ -1675,10 +1676,10 @@ Bundling your work together --------------------------- It is likely that you will be working on more than one thing at -a time. It is easy to use those more-or-less independent tasks +a time. It is easy to manage those more-or-less independent tasks using branches with git. -We have already seen how branches work in a previous example, +We have already seen how branches work previously, with "fun and work" example using two branches. The idea is the same if there are more than two branches. Let's say you started out from "master" head, and have some new code in the "master" -- cgit v1.2.3 From 64224caf888253601b7285ab242f4a12779894b9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 17:48:53 -0800 Subject: refs.c: make sure leading directories exist before writing a ref. Otherwise cloning a repository with hierarchical branch/tag over http would fail. Signed-off-by: Junio C Hamano --- refs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/refs.c b/refs.c index ac2619851d..d2aec73edc 100644 --- a/refs.c +++ b/refs.c @@ -292,6 +292,8 @@ int write_ref_sha1(const char *ref, int fd, const unsigned char *sha1) return -1; filename = ref_file_name(ref); lock_filename = ref_lock_file_name(ref); + if (safe_create_leading_directories(filename)) + die("unable to create leading directory for %s", filename); retval = write_ref_file(filename, lock_filename, fd, sha1); free(filename); free(lock_filename); @@ -358,6 +360,8 @@ int write_ref_sha1_unlocked(const char *ref, const unsigned char *sha1) return -1; filename = ref_file_name(ref); lock_filename = ref_lock_file_name(ref); + if (safe_create_leading_directories(filename)) + die("unable to create leading directory for %s", filename); fd = open(lock_filename, O_WRONLY | O_CREAT | O_EXCL, 0666); if (fd < 0) { error("Writing %s", lock_filename); -- cgit v1.2.3 From 128aed684d0b3099092b7597c8644599b45b7503 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Wed, 7 Dec 2005 21:04:38 -0500 Subject: Clean up file descriptors when calling hooks. When calling post-update hook, don't leave stdin and stdout connected to the pushing connection. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- receive-pack.c | 2 +- run-command.c | 15 +++++++++++++-- run-command.h | 3 +++ 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/receive-pack.c b/receive-pack.c index 1873506120..cbe37e7239 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -173,7 +173,7 @@ static void run_update_post_hook(struct command *cmd) argc++; } argv[argc] = NULL; - run_command_v(argc, argv); + run_command_v_opt(argc, argv, RUN_COMMAND_NO_STDIO); } /* diff --git a/run-command.c b/run-command.c index 5787a50955..8bf5922fc3 100644 --- a/run-command.c +++ b/run-command.c @@ -2,13 +2,19 @@ #include "run-command.h" #include -int run_command_v(int argc, char **argv) +int run_command_v_opt(int argc, char **argv, int flags) { pid_t pid = fork(); if (pid < 0) return -ERR_RUN_COMMAND_FORK; if (!pid) { + if (flags & RUN_COMMAND_NO_STDIO) { + int fd = open("/dev/null", O_RDWR); + dup2(fd, 0); + dup2(fd, 1); + close(fd); + } execvp(argv[0], (char *const*) argv); die("exec %s failed.", argv[0]); } @@ -36,6 +42,11 @@ int run_command_v(int argc, char **argv) } } +int run_command_v(int argc, char **argv) +{ + return run_command_v_opt(argc, argv, 0); +} + int run_command(const char *cmd, ...) { int argc; @@ -54,5 +65,5 @@ int run_command(const char *cmd, ...) va_end(param); if (MAX_RUN_COMMAND_ARGS <= argc) return error("too many args to run %s", cmd); - return run_command_v(argc, argv); + return run_command_v_opt(argc, argv, 0); } diff --git a/run-command.h b/run-command.h index 5ee0972241..2469eeaefb 100644 --- a/run-command.h +++ b/run-command.h @@ -11,6 +11,9 @@ enum { ERR_RUN_COMMAND_WAITPID_NOEXIT, }; +#define RUN_COMMAND_NO_STDIO 1 + +int run_command_v_opt(int argc, char **argv, int opt); int run_command_v(int argc, char **argv); int run_command(const char *cmd, ...); -- cgit v1.2.3 From 49ccb0877f64308662669a09db7b221419c13d0a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 7 Dec 2005 21:52:28 -0800 Subject: Make sure we use compat/subprocess.py with Python 2.3 while running tests. Otherwise the test will not succeed without installing. Signed-off-by: Junio C Hamano --- t/test-lib.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index f2eccd7918..0539dacc1c 100755 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -172,7 +172,18 @@ test_done () { # t/ subdirectory and are run in trash subdirectory. PATH=$(pwd)/..:$PATH GIT_EXEC_PATH=$(pwd)/.. -export GIT_EXEC_PATH +export PATH GIT_EXEC_PATH + +# Similarly use ../compat/subprocess.py if our python does not +# have subprocess.py on its own. +PYTHON=`sed -e '1{ + s/^#!// + q +}' ../git-merge-recursive` && +"$PYTHON" -c 'import subprocess' 2>/dev/null || { + PYTHONPATH=$(pwd)/../compat + export PYTHONPATH +} # Test repository test=trash -- cgit v1.2.3 From 9688a882e12a80bc94d6e34d5a4b34816990e9eb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 8 Dec 2005 14:04:33 -0800 Subject: Documentation: recursive is the default strategy these days. We still said resolve was the default in handful places. Signed-off-by: Junio C Hamano --- Documentation/git-fetch.txt | 2 +- Documentation/merge-options.txt | 2 +- Documentation/merge-strategies.txt | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/git-fetch.txt b/Documentation/git-fetch.txt index 438240c0cf..d1b45f96ed 100644 --- a/Documentation/git-fetch.txt +++ b/Documentation/git-fetch.txt @@ -18,7 +18,7 @@ the objects necessary to complete them. The ref names and their object names of fetched refs are stored in `.git/FETCH_HEAD`. This information is left for a later merge -operation done by "git resolve" or "git octopus". +operation done by "git merge". OPTIONS diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt index eebaf3aaff..53cc35590d 100644 --- a/Documentation/merge-options.txt +++ b/Documentation/merge-options.txt @@ -11,6 +11,6 @@ Use the given merge strategy; can be supplied more than once to specify them in the order they should be tried. If there is no `-s` option, a built-in list of strategies - is used instead (`git-merge-resolve` when merging a single + is used instead (`git-merge-recursive` when merging a single head, `git-merge-octopus` otherwise). diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt index 3ec56d22eb..7df0266ba8 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.txt @@ -6,27 +6,27 @@ resolve:: and another branch you pulled from) using 3-way merge algorithm. It tries to carefully detect criss-cross merge ambiguities and is considered generally safe and - fast. This is the default merge strategy when pulling - one branch. + fast. recursive:: This can only resolve two heads using 3-way merge algorithm. When there are more than one common ancestors that can be used for 3-way merge, it creates a - merged tree of the common ancestores and uses that as + merged tree of the common ancestors and uses that as the reference tree for the 3-way merge. This has been reported to result in fewer merge conflicts without causing mis-merges by tests done on actual merge commits taken from Linux 2.6 kernel development history. Additionally this can detect and handle merges involving - renames. + renames. This is the default merge strategy when + pulling or merging one branch. octopus:: This resolves more than two-head case, but refuses to do complex merge that needs manual resolution. It is primarily meant to be used for bundling topic branch heads together. This is the default merge strategy when - pulling more than one branch. + pulling or merging more than one branches. ours:: This resolves any number of heads, but the result of the -- cgit v1.2.3 From bcaf60b25b6f62049f195e253d6a974b42442066 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 8 Dec 2005 14:10:02 -0800 Subject: show-branch: comment typo Signed-off-by: Junio C Hamano --- show-branch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/show-branch.c b/show-branch.c index bff690d988..3cb335d68b 100644 --- a/show-branch.c +++ b/show-branch.c @@ -55,7 +55,7 @@ static void name_commit(struct commit *commit, const char *head_name, int nth) /* Parent is the first parent of the commit. We may name it * as (n+1)th generation ancestor of the same head_name as - * commit is nth generation ancestore of, if that generation + * commit is nth generation ancestor of, if that generation * number is better than the name it already has. */ static void name_parent(struct commit *commit, struct commit *parent) -- cgit v1.2.3 From 63ae26f87ae1d3a95a8ecc2fc761b7a7987e3ce5 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Document the --non-empty command-line option to git-pack-objects. This provides (minimal) documentation for the --non-empty command-line option to the pack-objects command. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-pack-objects.txt | 6 +++++- pack-objects.c | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index d1e93dbb37..009ec5ab37 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -8,7 +8,7 @@ git-pack-objects - Create a packed archive of objects. SYNOPSIS -------- -'git-pack-objects' [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list +'git-pack-objects' [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list DESCRIPTION @@ -70,6 +70,10 @@ base-name:: that are packed and not in the local object store (i.e. borrowed from an alternate). +--non-empty:: + Only create a packed archive if it would contain at + least one object. + Author ------ Written by Linus Torvalds diff --git a/pack-objects.c b/pack-objects.c index a62c9f8d18..caf3b6be5a 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -4,7 +4,7 @@ #include "pack.h" #include "csum-file.h" -static const char pack_usage[] = "git-pack-objects [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list"; +static const char pack_usage[] = "git-pack-objects [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list"; struct object_entry { unsigned char sha1[20]; -- cgit v1.2.3 From 68e37f8402d5ad33b423686558265e55655a2db6 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Fix the description of --utf8 and --keep to git-am. The git-am script actually transform --utf8 and --keep to -u and -k when sent to git-mailinfo. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-am.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 1ceed112f2..6645e82b84 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -28,7 +28,7 @@ OPTIONS area to store extracted patches. --utf8, --keep:: - Pass `--utf8` and `--keep` flags to `git-mailinfo` (see + Pass `-u` and `-k` flags to `git-mailinfo` (see gitlink:git-mailinfo[1]). --binary:: -- cgit v1.2.3 From 16cc50d12e8852583bde5c1116e4075f79d0a403 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Use uniform description for the '--' option. All descriptions of the '--' option were the same except for that in Documentation/git-merge-index.txt. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-merge-index.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-merge-index.txt b/Documentation/git-merge-index.txt index 60306429fb..fbc986aa84 100644 --- a/Documentation/git-merge-index.txt +++ b/Documentation/git-merge-index.txt @@ -20,7 +20,7 @@ files are passed as arguments 5, 6 and 7. OPTIONS ------- --:: - Interpret all following arguments as filenames. + Do not interpret any more arguments as options. -a:: Run merge against all files in the index that need merging. -- cgit v1.2.3 From eaa54efc619879ef0d0f7b95f5357d8dab86a713 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-commit.txt: Add long options and -- to documentation. Added the following long options to documentation: * --all * --signoff * --verify * --no-verify * --edit Also added documentation for the -- option for terminating option parsing. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-commit.txt | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt index 1edc278c64..b92cf48315 100644 --- a/Documentation/git-commit.txt +++ b/Documentation/git-commit.txt @@ -7,7 +7,7 @@ git-commit - Record your changes SYNOPSIS -------- -'git-commit' [-a] [-s] [-v] [(-c | -C) | -F | -m ] [-e] ... +'git-commit' [-a] [-s] [-v] [(-c | -C) | -F | -m ] [-e] [--] ... DESCRIPTION ----------- @@ -22,7 +22,7 @@ information. OPTIONS ------- --a:: +-a|--all:: Update all paths in the index file. -c or -C :: @@ -39,23 +39,29 @@ OPTIONS -m :: Use the given as the commit message. --s:: +-s|--signoff:: Add Signed-off-by line at the end of the commit message. --v:: +-v|--verify:: Look for suspicious lines the commit introduces, and abort committing if there is one. The definition of 'suspicious lines' is currently the lines that has trailing whitespaces, and the lines whose indentation has a SP character immediately followed by a TAB - character. + character. This is the default. --e:: +-n|--no-verify:: + The opposite of `--verify`. + +-e|--edit:: The message taken from file with `-F`, command line with `-m`, and from file with `-C` are usually used as the commit log message unmodified. This option lets you further edit the message taken from these sources. +--:: + Do not interpret any more arguments as options. + ...:: Update specified paths in the index file before committing. -- cgit v1.2.3 From e293de3efb9d49d0c66d8dc5817d1851f8b4a50c Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-verify-pack.txt: added documentation for --. The -- option has been added to the documentation of git-verify-pack. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-verify-pack.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/git-verify-pack.txt b/Documentation/git-verify-pack.txt index cd74ffd391..d032280e7c 100644 --- a/Documentation/git-verify-pack.txt +++ b/Documentation/git-verify-pack.txt @@ -8,7 +8,7 @@ git-verify-pack - Validate packed git archive files. SYNOPSIS -------- -'git-verify-pack' [-v] .idx ... +'git-verify-pack' [-v] [--] .idx ... DESCRIPTION @@ -25,6 +25,8 @@ OPTIONS -v:: After verifying the pack, show list of objects contained in the pack. +--:: + Do not interpret any more arguments as options. OUTPUT FORMAT ------------- -- cgit v1.2.3 From 56e5e9170e597f8ccba771cf2a7aa5de86e74799 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-cvsimport.txt: Fix a slight glitch in description heading. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-cvsimport.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-cvsimport.txt b/Documentation/git-cvsimport.txt index 88bd3b0f17..f89b251e1e 100644 --- a/Documentation/git-cvsimport.txt +++ b/Documentation/git-cvsimport.txt @@ -60,7 +60,7 @@ the old cvs2git tool. + If you need to pass multiple options, separate them with a comma. --P:: +-P :: Instead of calling cvsps, read the provided cvsps output file. Useful for debugging or when cvsps is being handled outside cvsimport. -- cgit v1.2.3 From d9722174573fc657c9b6c4adde6165d65c4e8de6 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-cherry-pick: Add --replay and --no-commit. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-cherry-pick.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index a7a883b83a..744f2c9ce2 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -24,7 +24,7 @@ OPTIONS With this option, `git-cherry-pick` will let you edit the commit message prior committing. --r:: +-r|--replay:: Usually the command appends which commit was cherry-picked after the original commit message when making a commit. This option, '--replay', causes it to @@ -32,7 +32,7 @@ OPTIONS when you are reordering the patches in your private tree before publishing. --n:: +-n|--no-commit:: Usually the command automatically creates a commit with a commit log message stating which commit was cherry-picked. This flag applies the change necessary -- cgit v1.2.3 From 674b28085e89c3be37d07063b253069101669b55 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Add documentation for git-revert and git-cherry-pick. * Added the -e option to the documentation of git-cherry-pick. * Added the -e and --no-commit option to git-revert. * Removed redundant case expression for -n as --no-edit (already taken by --no-commit). Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-cherry-pick.txt | 2 +- Documentation/git-revert.txt | 4 ++-- git-revert.sh | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt index 744f2c9ce2..4f323fa42a 100644 --- a/Documentation/git-cherry-pick.txt +++ b/Documentation/git-cherry-pick.txt @@ -20,7 +20,7 @@ OPTIONS :: Commit to cherry-pick. ---edit:: +-e|--edit:: With this option, `git-cherry-pick` will let you edit the commit message prior committing. diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt index f471037b97..e27c6808b3 100644 --- a/Documentation/git-revert.txt +++ b/Documentation/git-revert.txt @@ -20,7 +20,7 @@ OPTIONS :: Commit to revert. ---edit:: +-e|--edit:: With this option, `git-revert` will let you edit the commit message prior committing the revert. This is the default if you run the command from a terminal. @@ -29,7 +29,7 @@ OPTIONS With this option, `git-revert` will not start the commit message editor. --n:: +-n|--no-commit:: Usually the command automatically creates a commit with a commit log message stating which commit was reverted. This flag applies the change necessary to revert the diff --git a/git-revert.sh b/git-revert.sh index 5cb02b1ec2..9d499c4807 100755 --- a/git-revert.sh +++ b/git-revert.sh @@ -38,7 +38,7 @@ do -e|--e|--ed|--edi|--edit) edit=-e ;; - -n|--n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit) + --n|--no|--no-|--no-e|--no-ed|--no-edi|--no-edit) edit= ;; -r|--r|--re|--rep|--repl|--repla|--replay) -- cgit v1.2.3 From d4ce5f7e508c0a52aea2938cf2f7e25bf62eec3a Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Add documentation for the --topo-order option to git-show-branch. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-show-branch.txt | 8 +++++++- show-branch.c | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index 304101d818..ffe64d8353 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -7,7 +7,7 @@ git-show-branch - Show branches and their commits. SYNOPSIS -------- -'git-show-branch [--all] [--heads] [--tags] [--more= | --list | --independent | --merge-base] [--no-name | --sha1-name] [ | ]...' +'git-show-branch [--all] [--heads] [--tags] [--topo-order] [--more= | --list | --independent | --merge-base] [--no-name | --sha1-name] [ | ]...' DESCRIPTION ----------- @@ -35,6 +35,12 @@ OPTIONS Show all refs under $GIT_DIR/refs, $GIT_DIR/refs/heads, and $GIT_DIR/refs/tags, respectively. +--topo-order:: + By default, the branches and their commits are shown in + reverse chronological order. This option makes them + appear in topological order (i.e., descendant commits + are shown before their parents). + --more=:: Usually the command stops output upon showing the commit that is the common ancestor of all the branches. This diff --git a/show-branch.c b/show-branch.c index 3cb335d68b..ab158eb7d0 100644 --- a/show-branch.c +++ b/show-branch.c @@ -5,7 +5,7 @@ #include "refs.h" static const char show_branch_usage[] = -"git-show-branch [--all] [--heads] [--tags] [--more=count | --list | --independent | --merge-base ] [...]"; +"git-show-branch [--all] [--heads] [--tags] [--topo-order] [--more=count | --list | --independent | --merge-base ] [...]"; #define UNINTERESTING 01 -- cgit v1.2.3 From 6f855371a53bf6a906e573f9ff32a2f9e1dfcfa8 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-format-patch.txt: Add --signoff, --check, and long option-names. The documentation was lacking descriptions for the --signoff and --check options to git-format-patch. It was also missing the following long option-names: --output-directory (-o), --numbered (-n), --keep-subject (-k), --author (-a), --date (-d), and --mbox (-m). Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-format-patch.txt | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt index 7a3abec02e..abb8fc89f4 100644 --- a/Documentation/git-format-patch.txt +++ b/Documentation/git-format-patch.txt @@ -8,7 +8,7 @@ git-format-patch - Prepare patches for e-mail submission. SYNOPSIS -------- -'git-format-patch' [-n][-o |--stdout][-k][--mbox][--diff-options] [] +'git-format-patch' [-n | -k] [-o | --stdout] [-s] [-c] [--mbox] [--diff-options] [] DESCRIPTION ----------- @@ -32,23 +32,34 @@ processing with applymbox. OPTIONS ------- --o :: +-o|--output-directory :: Use to store the resulting files, instead of the current working directory. --n:: +-n|--numbered:: Name output in '[PATCH n/m]' format. --k:: +-k|--keep-subject:: Do not strip/add '[PATCH]' from the first line of the commit log message. ---author, --date:: +-a|--author, -d|--date:: Output From: and Date: headers for commits made by yourself as well. Usually these are output only for commits made by people other than yourself. ---mbox:: +-s|--signoff:: + Add `Signed-off-by:` line to the commit message, using + the committer identity of yourself. + +-c|--check:: + Display suspicious lines in the patch. The definition + of 'suspicious lines' is currently the lines that has + trailing whitespaces, and the lines whose indentation + has a SP character immediately followed by a TAB + character. + +-m|--mbox:: Format the output files for closer to mbox format by adding a phony Unix "From " line, so they can be concatenated together and fed to `git-applymbox`. -- cgit v1.2.3 From 5e34c99d95e1336b679a185f11747ee8392de9df Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-ls-remote.txt: Add -h and -t. -h and -t are aliases for --heads and --tags to git-ls-remote. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-ls-remote.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt index c0a80d4089..66fe60f998 100644 --- a/Documentation/git-ls-remote.txt +++ b/Documentation/git-ls-remote.txt @@ -17,7 +17,7 @@ Displays the references other repository has. OPTIONS ------- ---heads --tags:: +-h|--heads, -t|--tags:: Limit to only refs/heads and refs/tags, respectively. These options are _not_ mutually exclusive; when given both, references stored in refs/heads and refs/tags are -- cgit v1.2.3 From 31f232819f602d6df484837bbe4e021c5efd3586 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-repack.txt: Add -l and -n. This adds documentation for the -l and -n options to git-repack. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-repack.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Documentation/git-repack.txt b/Documentation/git-repack.txt index 0c1ae49ed7..9060fe8897 100644 --- a/Documentation/git-repack.txt +++ b/Documentation/git-repack.txt @@ -9,7 +9,7 @@ objects into pack files. SYNOPSIS -------- -'git-repack' [-a] [-d] +'git-repack' [-a] [-d] [-l] [-n] DESCRIPTION ----------- @@ -39,6 +39,13 @@ OPTIONS After packing, if the newly created packs make some existing packs redundant, remove the redundant packs. +-l:: + Pass the `--local` option to `git pack-objects`, see + gitlink:git-pack-objects[1]. + +-n:: + Do not update the server information with + `git update-server-info`. Author ------ -- cgit v1.2.3 From 5dd7342142f209b209e95b6a87c366d5205acd6a Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-http-fetch.txt: Document the commit-id argument. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-http-fetch.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/git-http-fetch.txt b/Documentation/git-http-fetch.txt index 088624f6cc..1116e855d6 100644 --- a/Documentation/git-http-fetch.txt +++ b/Documentation/git-http-fetch.txt @@ -14,6 +14,12 @@ DESCRIPTION ----------- Downloads a remote git repository via HTTP. +OPTIONS +------- +commit-id:: + Either the hash or the filename under [URL]/refs/ to + pull. + -c:: Get the commit objects. -t:: -- cgit v1.2.3 From 03f6c23c5edb2590c71e4e8c33f20c3449407a72 Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-update-server-info.txt: Add -f alias for --force to documentation. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-update-server-info.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-update-server-info.txt b/Documentation/git-update-server-info.txt index 3d0dea07fb..527fb303eb 100644 --- a/Documentation/git-update-server-info.txt +++ b/Documentation/git-update-server-info.txt @@ -22,7 +22,7 @@ pull decisions. This command generates such auxiliary files. OPTIONS ------- ---force:: +-f|--force:: Update the info files from scratch. -- cgit v1.2.3 From d839091d13c408cc0662e22830cab6ef36be74bf Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:05 +0100 Subject: Documentation/git-tag.txt: Fix the order of sections (DESCRIPTION should come before OPTIONS). Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-tag.txt | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 841c9dcf97..e8892bb0b0 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -10,26 +10,6 @@ SYNOPSIS -------- 'git-tag' [-a | -s | -u ] [-f | -d] [-m ] [] -OPTIONS -------- --a:: - Make an unsigned, annotated tag object - --s:: - Make a GPG-signed tag, using the default e-mail address's key - --u :: - Make a GPG-signed tag, using the given key - --f:: - Replace an existing tag with the given name (instead of failing) - --d:: - Delete an existing tag with the given name - --m :: - Use the given tag message (instead of prompting) - DESCRIPTION ----------- Adds a 'tag' reference in .git/refs/tags/ @@ -52,6 +32,26 @@ GnuPG key for signing. `-d ` deletes the tag. +OPTIONS +------- +-a:: + Make an unsigned, annotated tag object + +-s:: + Make a GPG-signed tag, using the default e-mail address's key + +-u :: + Make a GPG-signed tag, using the given key + +-f:: + Replace an existing tag with the given name (instead of failing) + +-d:: + Delete an existing tag with the given name + +-m :: + Use the given tag message (instead of prompting) + Author ------ -- cgit v1.2.3 From 8c667f4bb878a7bcb45eb6dbd920b8aba9718d7e Mon Sep 17 00:00:00 2001 From: Nikolai Weibull Date: Fri, 9 Dec 2005 00:28:06 +0100 Subject: Documentation/git-read-tree.txt: Add --reset to SYNOPSIS. Signed-off-by: Nikolai Weibull Signed-off-by: Junio C Hamano --- Documentation/git-read-tree.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-read-tree.txt b/Documentation/git-read-tree.txt index 27ee5909c9..6fbd6d9368 100644 --- a/Documentation/git-read-tree.txt +++ b/Documentation/git-read-tree.txt @@ -8,7 +8,7 @@ git-read-tree - Reads tree information into the index SYNOPSIS -------- -'git-read-tree' ( | [-m [-u|-i]] [ []]) +'git-read-tree' ( | [[-m | --reset] [-u | -i]] [ []]) DESCRIPTION -- cgit v1.2.3 From c82365dc6f211722cbbed96f41a61f477914c91a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 8 Dec 2005 16:30:24 -0800 Subject: Documentation: git-prune Not replacing but always including our own refs may be more desirable (and unarguably much safer), but at the same time I have a suspicion that that might be forbidding a useful usage I haven't thought of, so... Signed-off-by: Junio C Hamano --- Documentation/git-prune.txt | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt index 3367c9b214..05c8d4928e 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.txt @@ -8,7 +8,7 @@ git-prune - Prunes all unreachable objects from the object database SYNOPSIS -------- -'git-prune' [-n] +'git-prune' [-n] [--] [...] DESCRIPTION ----------- @@ -27,6 +27,34 @@ OPTIONS Do not remove anything; just report what it would remove. +--:: + Do not interpret any more arguments as options. + +...:: + Instead of keeping objects + reachable from any of our references, keep objects + reachable from only listed s. ++ +Note that the explicitly named s are *not* appended to the +default set of references, but they replace them. In general you +would want to say `git prune $(git-rev-parse --all) extra1 +extra2` to keep chains of commits leading to extra1, extra2, +... in addition to what are reachable from your own refs. +Saying `git prune extra1 extra2` would *lose* objects reachable +only from the usual refs, which is usually not what you want. + + +EXAMPLE +------- + +To prune objects not used by your repository and another that +borrows from your repository via its +`.git/objects/info/alternates`: + +------------ +$ git prune $(git-rev-parse --all) \ + $(cd ../another && $(git-rev-parse --all)) +------------ Author ------ -- cgit v1.2.3 From 2dee581667d62d113605e97de0beda6a9dbca153 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 8 Dec 2005 17:29:11 -0800 Subject: qsort(): ptrdiff_t may be larger than int This is a companion patch to e23eff8be92a2a2cb66b53deef020063cff285ed commit. The same logic, the same rationale that a comparison function that returns an int should not just compute a ptrdiff_t and return it. Signed-off-by: Junio C Hamano --- server-info.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server-info.c b/server-info.c index 7d7bcb2188..df19e49b5b 100644 --- a/server-info.c +++ b/server-info.c @@ -140,7 +140,12 @@ static int compare_info(const void *a_, const void *b_) return 1; /* then it does not matter but at least keep the comparison stable */ - return (*a)->p - (*b)->p; + if ((*a)->p == (*b)->p) + return 0; + else if ((*a)->p < (*b)->p) + return -1; + else + return 1; } static void init_pack_info(const char *infofile, int force) -- cgit v1.2.3 From 2b86976bfd6e42609692d57fffaef72bd985c23a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 8 Dec 2005 23:18:41 -0800 Subject: git-prune: never lose objects reachable from our refs. Explicit arguments to git-prune replaces, instead of extends, the list of heads used for reachability analysis by fsck-objects. By giving a subset of heads by mistake, objects reachable only from other heads can be removed, resulting in a corrupted repository. This commit stops replacing the list of heads, and makes the command line arguments to add to them instead for safety. Signed-off-by: Junio C Hamano --- Documentation/git-prune.txt | 27 +++++++++------------------ git-prune.sh | 6 +++++- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt index 05c8d4928e..f694fcbde8 100644 --- a/Documentation/git-prune.txt +++ b/Documentation/git-prune.txt @@ -13,10 +13,11 @@ SYNOPSIS DESCRIPTION ----------- -This runs `git-fsck-objects --unreachable` using the heads -specified on the command line (or `$GIT_DIR/refs/heads/\*` and -`$GIT_DIR/refs/tags/\*` if none is specified), and prunes all -unreachable objects from the object database. In addition, it +This runs `git-fsck-objects --unreachable` using all the refs +available in `$GIT_DIR/refs`, optionally with additional set of +objects specified on the command line, and prunes all +objects unreachable from any of these head objects from the object database. +In addition, it prunes the unpacked objects that are also found in packs by running `git prune-packed`. @@ -31,29 +32,19 @@ OPTIONS Do not interpret any more arguments as options. ...:: - Instead of keeping objects + In addition to objects reachable from any of our references, keep objects - reachable from only listed s. -+ -Note that the explicitly named s are *not* appended to the -default set of references, but they replace them. In general you -would want to say `git prune $(git-rev-parse --all) extra1 -extra2` to keep chains of commits leading to extra1, extra2, -... in addition to what are reachable from your own refs. -Saying `git prune extra1 extra2` would *lose* objects reachable -only from the usual refs, which is usually not what you want. - + reachable from listed s. EXAMPLE ------- -To prune objects not used by your repository and another that +To prune objects not used by your repository nor another that borrows from your repository via its `.git/objects/info/alternates`: ------------ -$ git prune $(git-rev-parse --all) \ - $(cd ../another && $(git-rev-parse --all)) +$ git prune $(cd ../another && $(git-rev-parse --all)) ------------ Author diff --git a/git-prune.sh b/git-prune.sh index 1fd8c731cd..7e7f0ad56d 100755 --- a/git-prune.sh +++ b/git-prune.sh @@ -16,7 +16,11 @@ do done sync -git-fsck-objects --full --cache --unreachable "$@" | +case "$#" in +0) git-fsck-objects --full --cache --unreachable ;; +*) git-fsck-objects --full --cache --unreachable $(git-rev-parse --all) "$@" ;; +esac | + sed -ne '/unreachable /{ s/unreachable [^ ][^ ]* // s|\(..\)|\1/|p -- cgit v1.2.3 From 0f737464a6734d917431cf8df14eb04bd9c4cd8d Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Thu, 8 Dec 2005 21:25:55 +0100 Subject: use "git init-db" in tests This is to catch an error where tests are run without first building what are being tested. Relying on prefixing $PATH with the build directory and expect that the PATH mechanism would find what we just built would silently run an already installed binaries from the PATH. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- t/test-lib.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index 0539dacc1c..3704e5faf0 100755 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -190,8 +190,8 @@ test=trash rm -fr "$test" mkdir "$test" cd "$test" -git-init-db --template=../../templates/blt/ 2>/dev/null || -error "cannot run git-init-db" +git init-db --template=../../templates/blt/ 2>/dev/null || +error "cannot run git init-db" mv .git/hooks .git/hooks-disabled -- cgit v1.2.3 From 10b94e283aa76d56b85cfc9fcb8bc63f167b580b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 9 Dec 2005 17:32:18 -0800 Subject: Use GIT_EXEC_PATH explicitly for initial git-init-db in tests. This is just a belts-and-suspenders check, but makes sure we have both "git" and "git-init-db" built, executable, and checking. Signed-off-by: Junio C Hamano --- t/test-lib.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/t/test-lib.sh b/t/test-lib.sh index 3704e5faf0..447d9e2517 100755 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -149,7 +149,7 @@ test_expect_code () { test_done () { trap - exit case "$test_failure" in - 0) + 0) # We could: # cd .. && rm -fr trash # but that means we forbid any tests that use their own @@ -190,8 +190,7 @@ test=trash rm -fr "$test" mkdir "$test" cd "$test" -git init-db --template=../../templates/blt/ 2>/dev/null || +"$GIT_EXEC_PATH/git" init-db --template=../../templates/blt/ 2>/dev/null || error "cannot run git init-db" mv .git/hooks .git/hooks-disabled - -- cgit v1.2.3 From db9536c8566bc7b2f2dd388a066bb0fda960b379 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 9 Dec 2005 23:07:29 -0800 Subject: Everyday GIT with 20 commands Signed-off-by: Junio C Hamano --- Documentation/Makefile | 1 + Documentation/everyday.txt | 138 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 Documentation/everyday.txt diff --git a/Documentation/Makefile b/Documentation/Makefile index be4f3e13c6..a1ff2c2170 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -9,6 +9,7 @@ ARTICLES += diffcore ARTICLES += howto-index ARTICLES += repository-layout ARTICLES += hooks +ARTICLES += everyday # with their own formatting rules. SP_ARTICLES = glossary howto/revert-branch-rebase diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt new file mode 100644 index 0000000000..3851a040f9 --- /dev/null +++ b/Documentation/everyday.txt @@ -0,0 +1,138 @@ +Everyday GIT With 20 Commands Or So +=================================== + +GIT suite has over 100 commands, and the manual page for each of +them discusses what the command does and how it is used in +detail, but until you know what command should be used in order +to achieve what you want to do, you cannot tell which manual +page to look at, and if you know that already you do not need +the manual. + +Does that mean you need to know all of them before you can use +git? Not at all. Depending on the role you play, the set of +commands you need to know is slightly different, but in any case +what you need to learn is far smaller than the full set of +commands to carry out your day-to-day work. This document is to +serve as a cheat-sheet and a set of pointers for people playing +various roles. + +<> commands are needed by people who has a +repository --- that is everybody, because every working tree of +git is a repository. + +In addition, <> commands are +essential for anybody who makes a commit, even for somebody who +works alone. + +If you work with other people, you will need commands listed in +<> section as well. + +People who play <> role need to learn some more +commands in addition to the above. + +<> commands are for system +administrators who are responsible to care and feed git +repositories to support developers. + + +Basic Repository[[Basic Repository]] +------------------------------------ + +Everybody uses these commands to feed and care git repositories. + + * gitlink:git-init-db[1] or gitlink:git-clone[1] to create a + new repository. + + * gitlink:git-fsck-objects[1] to validate the repository. + + * gitlink:git-prune[1] to garbage collect crufts in the + repository. + + * gitlink:git-repack[1] to pack loose objects for efficiency. + +Individual Developer (Standalone)[[Individual Developer (Standalone)]] +---------------------------------------------------------------------- + +A standalone individual developer does not exchange patches with +other poeple, and works alone in a single repository, using the +following commands. + + * gitlink:git-show-branch[1] to see where you are. + + * gitlink:git-diff[1] and gitlink:git-status[1] to see what + you are in the middle of doing. + + * gitlink:git-log[1] to see what happened. + + * gitlink:git-whatchanged[1] to find out where things have + come from. + + * gitlink:git-checkout[1] and gitlink:git-branch[1] to switch + branches. + + * gitlink:git-update-index[1] to manage the index file. + + * gitlink:git-commit[1] to advance the current branch. + + * gitlink:git-reset[1] and gitlink:git-checkout[1] (with + pathname parameters) to undo changes. + + * gitlink:git-pull[1] with "." as the remote to merge between + local branches. + + * gitlink:git-rebase[1] to maintain topic branches. + + +Individual Developer (Participant)[[Individual Developer (Participant)]] +------------------------------------------------------------------------ + +A developer working as a participant in a group project needs to +learn how to communicate with others, and uses these commands in +addition to the ones needed by a standalone developer. + + * gitlink:git-pull[1] from "origin" to keep up-to-date with + the upstream. + + * gitlink:git-push[1] to shared repository if you adopt CVS + style shared repository workflow. + + * gitlink:git-format-patch[1] to prepare e-mail submission, if + you adopt Linux kernel-style public forum workflow. + + +Integrator[[Integrator]] +------------------------ + +A fairly central person acting as the integrator in a group +project receives changes made by others, reviews and integrates +them and publishes the result for others to use, using these +commands in addition to the ones needed by participants. + + * gitlink:git-am[1] to apply patches e-mailed in from your + contributors. + + * gitlink:git-pull[1] to merge from your trusted lieutenants. + + * gitlink:git-format-patch[1] to prepare and send suggested + alternative to contributors. + + * gitlink:git-revert[1] to undo botched commits. + + * gitlink:git-push[1] to publish the bleeding edge. + + +Repository Administration[[Repository Administration]] +------------------------------------------------------ + +A repository administrator uses the following tools to set up +and maintain access to the repository by developers. + + * gitlink:git-daemon[1] to allow anonymous download from + repository. + + * gitlink:git-shell[1] can be used as a 'restricted login shell' + for shared central repository users. + + * howto/update-hook-example has a good example of + managing a shared central repository. + -- cgit v1.2.3 From 8b15e2fbc9d9b9d04c70fe590a3d0562d4334c38 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 9 Dec 2005 23:41:03 -0800 Subject: Link Everyday GIT to main documentation tree. Signed-off-by: Junio C Hamano --- Documentation/everyday.txt | 4 ++-- Documentation/git.txt | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Documentation/everyday.txt b/Documentation/everyday.txt index 3851a040f9..5775cd28ac 100644 --- a/Documentation/everyday.txt +++ b/Documentation/everyday.txt @@ -133,6 +133,6 @@ and maintain access to the repository by developers. * gitlink:git-shell[1] can be used as a 'restricted login shell' for shared central repository users. - * howto/update-hook-example has a good example of - managing a shared central repository. + * link:howto/update-hook-example.txt[update hook howto] has a + good example of managing a shared central repository. diff --git a/Documentation/git.txt b/Documentation/git.txt index fc11516deb..45773db135 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -36,23 +36,24 @@ OPTIONS CORE GIT COMMANDS ----------------- Before reading this cover to cover, you may want to take a look -at the link:tutorial.html[tutorial] document. +at the link:tutorial.html[tutorial] document. If you are +migrating from CVS, link:cvs-migration.html[cvs migration] +document may be helpful after you finish the tutorial. The <> section below contains much useful definition and clarification info - read that first. After that, if you are interested in using git to manage (version control) -projects, read on commands listed in Porcelain-ish commands -section next. On the other hand, if you are writing your own -Porcelain, I suggest reading gitlink:git-update-index[1] and -gitlink:git-read-tree[1] first. - -If you are migrating from CVS, link:cvs-migration.html[cvs migration] -document may be helpful after you finish the tutorial. +projects, use link:everyday.html[Everyday GIT] as a guide to the +minimum set of commands you need to know for day-to-day work. After you get the general feel from the tutorial and this overview page, you may want to take a look at the link:howto-index.html[howto] documents. +If you are writing your own Porcelain, you need to be familiar +with most of the low level commands --- I suggest starting from +gitlink:git-update-index[1] and gitlink:git-read-tree[1]. + David Greaves 08/05/05 -- cgit v1.2.3 From 2777ef76be7174f698b3f53cc4ff38b4118de320 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:47:39 -0800 Subject: archimport: first, make sure it still compiles (ML: And introduce safe_pipe_capture()) Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/git-archimport.perl b/git-archimport.perl index c3bed08086..b5f8a2c64b 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -99,6 +99,7 @@ my %psets = (); # the collection, by name my %rptags = (); # my reverse private tags # to map a SHA1 to a commitid +my $TLA = $ENV{'ARCH_CLIENT'} || 'tla'; foreach my $root (@arch_roots) { my ($arepo, $abranch) = split(m!/!, $root); @@ -850,3 +851,18 @@ sub commitid2pset { || (print Dumper(sort keys %psets)) && die "Cannot find patchset for $name"; return $ps; } + +# an alterative to `command` that allows input to be passed as an array +# to work around shell problems with weird characters in arguments +sub safe_pipe_capture { + my @output; + if (my $pid = open my $child, '-|') { + @output = (<$child>); + close $child or die join(' ',@_).": $! $?"; + } else { + exec(@_) or die $?; # exec() can fail the executable can't be found + } + return wantarray ? @output : join('',@output); +} + + -- cgit v1.2.3 From f88961a85f14dd3fae4f5204f8187ba5d9a7646e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:48:57 -0800 Subject: archimport: remove String::ShellQuote dependency. use safe_pipe_capture() or system() over backticks where shellquoting may have been necessary. More changes planned, so I'm not touching the parts I'm planning on replacing entirely. Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 51 ++++++++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/git-archimport.perl b/git-archimport.perl index b5f8a2c64b..b7e24808ec 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -55,9 +55,8 @@ use warnings; use Getopt::Std; use File::Spec; use File::Temp qw(tempfile tempdir); -use File::Path qw(mkpath); +use File::Path qw(mkpath rmtree); use File::Basename qw(basename dirname); -use String::ShellQuote; use Time::Local; use IO::Socket; use IO::Pipe; @@ -306,7 +305,7 @@ foreach my $ps (@psets) { unless ($import) { # skip for import if ( -e "$git_dir/refs/heads/$ps->{branch}") { # we know about this branch - `git checkout $ps->{branch}`; + system('git-checkout',$ps->{branch}); } else { # new branch! we need to verify a few things die "Branch on a non-tag!" unless $ps->{type} eq 't'; @@ -315,7 +314,7 @@ foreach my $ps (@psets) { unless $branchpoint; # find where we are supposed to branch from - `git checkout -b $ps->{branch} $branchpoint`; + system('git-checkout','-b',$ps->{branch},$branchpoint); # If we trust Arch with the fact that this is just # a tag, and it does not affect the state of the tree @@ -344,7 +343,7 @@ foreach my $ps (@psets) { # my $tree; - my $commitlog = `tla cat-archive-log -A $ps->{repo} $ps->{id}`; + my $commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); die "Error in cat-archive-log: $!" if $?; # parselog will git-add/rm files @@ -422,7 +421,7 @@ foreach my $ps (@psets) { # my @par; if ( -e "$git_dir/refs/heads/$ps->{branch}") { - if (open HEAD, "<$git_dir/refs/heads/$ps->{branch}") { + if (open HEAD, "<","$git_dir/refs/heads/$ps->{branch}") { my $p = ; close HEAD; chomp $p; @@ -437,7 +436,6 @@ foreach my $ps (@psets) { if ($ps->{merges}) { push @par, find_parents($ps); } - my $par = join (' ', @par); # # Commit, tag and clean state @@ -454,7 +452,7 @@ foreach my $ps (@psets) { $commit_rh = 'commit_rh'; $commit_wh = 'commit_wh'; - $pid = open2(*READER, *WRITER, "git-commit-tree $tree $par") + $pid = open2(*READER, *WRITER,'git-commit-tree',$tree,@par) or die $!; print WRITER $logmessage; # write close WRITER; @@ -469,7 +467,7 @@ foreach my $ps (@psets) { # # Update the branch # - open HEAD, ">$git_dir/refs/heads/$ps->{branch}"; + open HEAD, ">","$git_dir/refs/heads/$ps->{branch}"; print HEAD $commitid; close HEAD; system('git-update-ref', 'HEAD', "$ps->{branch}"); @@ -483,21 +481,23 @@ foreach my $ps (@psets) { print " + tree $tree\n"; print " + commit $commitid\n"; $opt_v && print " + commit date is $ps->{date} \n"; - $opt_v && print " + parents: $par \n"; + $opt_v && print " + parents: ",join(' ',@par),"\n"; } sub apply_import { my $ps = shift; my $bname = git_branchname($ps->{id}); - `mkdir -p $tmp`; + mkpath($tmp); - `tla get -s --no-pristine -A $ps->{repo} $ps->{id} $tmp/import`; + safe_pipe_capture($TLA,'get','-s','--no-pristine',$ps->{id},"$tmp/import"); die "Cannot get import: $!" if $?; - `rsync -v --archive --delete --exclude '$git_dir' --exclude '.arch-ids' --exclude '{arch}' $tmp/import/* ./`; + system('rsync','-aI','--delete', '--exclude',$git_dir, + '--exclude','.arch-ids','--exclude','{arch}', + "$tmp/import/", './'); die "Cannot rsync import:$!" if $?; - `rm -fr $tmp/import`; + rmtree("$tmp/import"); die "Cannot remove tempdir: $!" if $?; @@ -507,10 +507,10 @@ sub apply_import { sub apply_cset { my $ps = shift; - `mkdir -p $tmp`; + mkpath($tmp); # get the changeset - `tla get-changeset -A $ps->{repo} $ps->{id} $tmp/changeset`; + safe_pipe_capture($TLA,'get-changeset',$ps->{id},"$tmp/changeset"); die "Cannot get changeset: $!" if $?; # apply patches @@ -534,17 +534,20 @@ sub apply_cset { $orig =~ s/\.modified$//; # lazy $orig =~ s!^\Q$tmp\E/changeset/patches/!!; #print "rsync -p '$mod' '$orig'"; - `rsync -p $mod ./$orig`; + system('rsync','-p',$mod,"./$orig"); die "Problem applying binary changes! $!" if $?; } } # bring in new files - `rsync --archive --exclude '$git_dir' --exclude '.arch-ids' --exclude '{arch}' $tmp/changeset/new-files-archive/* ./`; + system('rsync','-aI','--exclude',$git_dir, + '--exclude','.arch-ids', + '--exclude', '{arch}', + "$tmp/changeset/new-files-archive/",'./'); # deleted files are hinted from the commitlog processing - `rm -fr $tmp/changeset`; + rmtree("$tmp/changeset"); } @@ -622,9 +625,9 @@ sub parselog { # tla cat-archive-log will give us filenames with spaces as file\(sp)name - why? # we can assume that any filename with \ indicates some pika escaping that we want to get rid of. if ($t =~ /\\/ ){ - $t = `tla escape --unescaped '$t'`; + $t = (safe_pipe_capture($TLA,'escape','--unescaped',$t))[0]; } - push (@tmp, shell_quote($t)); + push (@tmp, $t); } @$ref = @tmp; } @@ -827,8 +830,10 @@ sub find_parents { } } } - @parents = keys %parents; - @parents = map { " -p " . ptag($_) } @parents; + @parents = (); + foreach (keys %parents) { + push @parents, '-p', ptag($_); + } return @parents; } -- cgit v1.2.3 From 5744f27794c284758a5c7956b9e5d5669c5dd318 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:50:27 -0800 Subject: archimport: fix -t tmpdir switch set TMPDIR env correctly if -t is passed from the command-line. setting TMPDIR => 1 as an argument to tempdir() has no effect otherwise Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/git-archimport.perl b/git-archimport.perl index b7e24808ec..2ed2e3c065 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -88,9 +88,8 @@ usage if $opt_h; @ARGV >= 1 or usage(); my @arch_roots = @ARGV; -my ($tmpdir, $tmpdirname) = tempdir('git-archimport-XXXXXX', TMPDIR => 1, CLEANUP => 1); -my $tmp = $opt_t || 1; -$tmp = tempdir('git-archimport-XXXXXX', TMPDIR => 1, CLEANUP => 1); +$ENV{'TMPDIR'} = $opt_t if $opt_t; # $ENV{TMPDIR} will affect tempdir() calls: +my $tmp = tempdir('git-archimport-XXXXXX', TMPDIR => 1, CLEANUP => 1); $opt_v && print "+ Using $tmp as temporary directory\n"; my @psets = (); # the collection -- cgit v1.2.3 From 1136fb5284a5be907a28d887811e8c08aaa3b4da Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:51:33 -0800 Subject: archimport: remove git wrapper dependency use git-diff-files instead of git diff-files so we don't rely on the wrapper being installed (some people may have git as GNU interactive tools :) Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-archimport.perl b/git-archimport.perl index 2ed2e3c065..938fa2bbf3 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -278,7 +278,7 @@ foreach my $ps (@psets) { # # ensure we have a clean state # - if (`git diff-files`) { + if (`git-diff-files`) { die "Unclean tree when about to process $ps->{id} " . " - did we fail to commit cleanly before?"; } -- cgit v1.2.3 From 42f44b08bc1bf84a6e620cf7254b820a9656daca Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:52:43 -0800 Subject: archimport: add -D and -a switch add -D option to abrowse add -a switch to attempt to auto-register archives at mirrors.sourcecontrol.net (ML: Also removes some std libraries no longer in use) Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 225 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 135 insertions(+), 90 deletions(-) diff --git a/git-archimport.perl b/git-archimport.perl index 938fa2bbf3..396874080a 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -53,14 +53,9 @@ and can contain multiple, unrelated branches. use strict; use warnings; use Getopt::Std; -use File::Spec; -use File::Temp qw(tempfile tempdir); +use File::Temp qw(tempdir); use File::Path qw(mkpath rmtree); use File::Basename qw(basename dirname); -use Time::Local; -use IO::Socket; -use IO::Pipe; -use POSIX qw(strftime dup2); use Data::Dumper qw/ Dumper /; use IPC::Open2; @@ -71,27 +66,33 @@ my $git_dir = $ENV{"GIT_DIR"} || ".git"; $ENV{"GIT_DIR"} = $git_dir; my $ptag_dir = "$git_dir/archimport/tags"; -our($opt_h,$opt_v, $opt_T,$opt_t,$opt_o); +our($opt_h,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o); sub usage() { print STDERR <= 1 or usage(); -my @arch_roots = @ARGV; +# $arch_branches: +# values associated with keys: +# =1 - Arch version / git 'branch' detected via abrowse on a limit +# >1 - Arch version / git 'branch' of an auxilliary branch we've merged +my %arch_branches = map { $_ => 1 } @ARGV; $ENV{'TMPDIR'} = $opt_t if $opt_t; # $ENV{TMPDIR} will affect tempdir() calls: my $tmp = tempdir('git-archimport-XXXXXX', TMPDIR => 1, CLEANUP => 1); $opt_v && print "+ Using $tmp as temporary directory\n"; +my %reachable = (); # Arch repositories we can access +my %unreachable = (); # Arch repositories we can't access :< my @psets = (); # the collection my %psets = (); # the collection, by name @@ -99,96 +100,112 @@ my %rptags = (); # my reverse private tags # to map a SHA1 to a commitid my $TLA = $ENV{'ARCH_CLIENT'} || 'tla'; -foreach my $root (@arch_roots) { - my ($arepo, $abranch) = split(m!/!, $root); - open ABROWSE, "tla abrowse -f -A $arepo --desc --merges $abranch |" - or die "Problems with tla abrowse: $!"; +sub do_abrowse { + my $stage = shift; + while (my ($limit, $level) = each %arch_branches) { + next unless $level == $stage; + + open ABROWSE, "$TLA abrowse -fkD --merges $limit |" + or die "Problems with tla abrowse: $!"; - my %ps = (); # the current one - my $mode = ''; - my $lastseen = ''; + my %ps = (); # the current one + my $lastseen = ''; - while () { - chomp; - - # first record padded w 8 spaces - if (s/^\s{8}\b//) { + while () { + chomp; - # store the record we just captured - if (%ps) { - my %temp = %ps; # break references - push (@psets, \%temp); - $psets{$temp{id}} = \%temp; - %ps = (); - } - - my ($id, $type) = split(m/\s{3}/, $_); - $ps{id} = $id; - $ps{repo} = $arepo; - - # deal with types - if ($type =~ m/^\(simple changeset\)/) { - $ps{type} = 's'; - } elsif ($type eq '(initial import)') { - $ps{type} = 'i'; - } elsif ($type =~ m/^\(tag revision of (.+)\)/) { - $ps{type} = 't'; - $ps{tag} = $1; - } else { - warn "Unknown type $type"; - } - $lastseen = 'id'; - } - - if (s/^\s{10}//) { - # 10 leading spaces or more - # indicate commit metadata - - # date & author - if ($lastseen eq 'id' && m/^\d{4}-\d{2}-\d{2}/) { + # first record padded w 8 spaces + if (s/^\s{8}\b//) { + my ($id, $type) = split(m/\s+/, $_, 2); + + my %last_ps; + # store the record we just captured + if (%ps && !exists $psets{ $ps{id} }) { + %last_ps = %ps; # break references + push (@psets, \%last_ps); + $psets{ $last_ps{id} } = \%last_ps; + } - my ($date, $authoremail) = split(m/\s{2,}/, $_); - $ps{date} = $date; - $ps{date} =~ s/\bGMT$//; # strip off trailign GMT - if ($ps{date} =~ m/\b\w+$/) { - warn 'Arch dates not in GMT?! - imported dates will be wrong'; + my $branch = extract_versionname($id); + %ps = ( id => $id, branch => $branch ); + if (%last_ps && ($last_ps{branch} eq $branch)) { + $ps{parent_id} = $last_ps{id}; + } + + $arch_branches{$branch} = 1; + $lastseen = 'id'; + + # deal with types (should work with baz or tla): + if ($type =~ m/\(.*changeset\)/) { + $ps{type} = 's'; + } elsif ($type =~ /\(.*import\)/) { + $ps{type} = 'i'; + } elsif ($type =~ m/\(tag.*\)/) { + $ps{type} = 't'; + # read which revision we've tagged when we parse the log + #$ps{tag} = $1; + } else { + warn "Unknown type $type"; + } + + $arch_branches{$branch} = 1; + $lastseen = 'id'; + } elsif (s/^\s{10}//) { + # 10 leading spaces or more + # indicate commit metadata + + # date + if ($lastseen eq 'id' && m/^(\d{4}-\d\d-\d\d \d\d:\d\d:\d\d)/){ + $ps{date} = $1; + $lastseen = 'date'; + } elsif ($_ eq 'merges in:') { + $ps{merges} = []; + $lastseen = 'merges'; + } elsif ($lastseen eq 'merges' && s/^\s{2}//) { + my $id = $_; + push (@{$ps{merges}}, $id); + + # aggressive branch finding: + if ($opt_D) { + my $branch = extract_versionname($id); + my $repo = extract_reponame($branch); + + if (archive_reachable($repo) && + !defined $arch_branches{$branch}) { + $arch_branches{$branch} = $stage + 1; + } + } + } else { + warn "more metadata after merges!?: $_\n" unless /^\s*$/; } - - $authoremail =~ m/^(.+)\s(\S+)$/; - $ps{author} = $1; - $ps{email} = $2; - - $lastseen = 'date'; - - } elsif ($lastseen eq 'date') { - # the only hint is position - # subject is after date - $ps{subj} = $_; - $lastseen = 'subj'; - - } elsif ($lastseen eq 'subj' && $_ eq 'merges in:') { - $ps{merges} = []; - $lastseen = 'merges'; - - } elsif ($lastseen eq 'merges' && s/^\s{2}//) { - push (@{$ps{merges}}, $_); - } else { - warn 'more metadata after merges!?'; } - } - } - if (%ps) { - my %temp = %ps; # break references - push (@psets, \%temp); - $psets{ $temp{id} } = \%temp; - %ps = (); - } - close ABROWSE; + if (%ps && !exists $psets{ $ps{id} }) { + my %temp = %ps; # break references + if (@psets && $psets[$#psets]{branch} eq $ps{branch}) { + $temp{parent_id} = $psets[$#psets]{id}; + } + push (@psets, \%temp); + $psets{ $temp{id} } = \%temp; + } + + close ABROWSE or die "$TLA abrowse failed on $limit\n"; + } } # end foreach $root +do_abrowse(1); +my $depth = 2; +$opt_D ||= 0; +while ($depth <= $opt_D) { + do_abrowse($depth); + $depth++; +} + ## Order patches by time +# FIXME see if we can find a more optimal way to do this by graphing +# the ancestry data and walking it, that way we won't have to rely on +# client-supplied dates @psets = sort {$a->{date}.$b->{id} cmp $b->{date}.$b->{id}} @psets; #print Dumper \@psets; @@ -209,7 +226,7 @@ unless (-d $git_dir) { # initial import } } else { # progressing an import # load the rptags - opendir(DIR, "$git_dir/archimport/tags") + opendir(DIR, $ptag_dir) || die "can't opendir: $!"; while (my $file = readdir(DIR)) { # skip non-interesting-files @@ -829,6 +846,7 @@ sub find_parents { } } } + @parents = (); foreach (keys %parents) { push @parents, '-p', ptag($_); @@ -856,6 +874,7 @@ sub commitid2pset { return $ps; } + # an alterative to `command` that allows input to be passed as an array # to work around shell problems with weird characters in arguments sub safe_pipe_capture { @@ -869,4 +888,30 @@ sub safe_pipe_capture { return wantarray ? @output : join('',@output); } +# `tla logs -rf -d | head -n1` or `baz tree-id ` +sub arch_tree_id { + my $dir = shift; + chomp( my $ret = (safe_pipe_capture($TLA,'logs','-rf','-d',$dir))[0] ); + return $ret; +} + +sub archive_reachable { + my $archive = shift; + return 1 if $reachable{$archive}; + return 0 if $unreachable{$archive}; + + if (system "$TLA whereis-archive $archive >/dev/null") { + if ($opt_a && (system($TLA,'register-archive', + "http://mirrors.sourcecontrol.net/$archive") == 0)) { + $reachable{$archive} = 1; + return 1; + } + print STDERR "Archive is unreachable: $archive\n"; + $unreachable{$archive} = 1; + return 0; + } else { + $reachable{$archive} = 1; + return 1; + } +} -- cgit v1.2.3 From 6df896b50a8f1294d00e8da9d3662d9422dd0533 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:53:55 -0800 Subject: archimport: safer log file parsing Better logfile parsing, no longer confused by 'headers' after the first blank line. Re-enabled tag-reading with abrowse (baz and tla compatible) Remove need to quote args to external processes Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 209 ++++++++++++++++++++++++++++------------------------ 1 file changed, 111 insertions(+), 98 deletions(-) diff --git a/git-archimport.perl b/git-archimport.perl index 396874080a..8676f35f0f 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -140,10 +140,10 @@ sub do_abrowse { $ps{type} = 's'; } elsif ($type =~ /\(.*import\)/) { $ps{type} = 'i'; - } elsif ($type =~ m/\(tag.*\)/) { + } elsif ($type =~ m/\(tag.*?(\S+\@\S+).*?\)/) { $ps{type} = 't'; # read which revision we've tagged when we parse the log - #$ps{tag} = $1; + $ps{tag} = $1; } else { warn "Unknown type $type"; } @@ -359,78 +359,73 @@ foreach my $ps (@psets) { # my $tree; - my $commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); + my @commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); die "Error in cat-archive-log: $!" if $?; - # parselog will git-add/rm files - # and generally prepare things for the commit - # NOTE: parselog will shell-quote filenames! - my ($sum, $msg, $add, $del, $mod, $ren) = parselog($commitlog); - my $logmessage = "$sum\n$msg"; - + parselog($ps,\@commitlog); # imports don't give us good info # on added files. Shame on them - if ($ps->{type} eq 'i' || $ps->{type} eq 't') { - `find . -type f -print0 | grep -zv '^./$git_dir' | xargs -0 -l100 git-update-index --add`; - `git-ls-files --deleted -z | xargs --no-run-if-empty -0 -l100 git-update-index --remove`; + if ($ps->{type} eq 'i' || $ps->{type} eq 't') { + system('git-ls-files --others -z | '. + 'git-update-index --add -z --stdin') == 0 or die "$! $?\n"; + system('git-ls-files --deleted -z | '. + 'git-update-index --remove -z --stdin') == 0 or die "$! $?\n"; } - if (@$add) { + # TODO: handle removed_directories and renamed_directories: + + if (my $add = $ps->{new_files}) { while (@$add) { my @slice = splice(@$add, 0, 100); - my $slice = join(' ', @slice); - `git-update-index --add $slice`; - die "Error in git-update-index --add: $!" if $?; + system('git-update-index','--add','--',@slice) == 0 or + die "Error in git-update-index --add: $! $?\n"; } } - if (@$del) { - foreach my $file (@$del) { - unlink $file or die "Problems deleting $file : $!"; - } + + if (my $del = $ps->{removed_files}) { + unlink @$del; while (@$del) { my @slice = splice(@$del, 0, 100); - my $slice = join(' ', @slice); - `git-update-index --remove $slice`; - die "Error in git-update-index --remove: $!" if $?; + system('git-update-index','--remove','--',@slice) == 0 or + die "Error in git-update-index --remove: $! $?\n"; } } - if (@$ren) { # renamed + + if (my $ren = $ps->{renamed_files}) { # renamed if (@$ren % 2) { die "Odd number of entries in rename!?"; } - ; + while (@$ren) { - my $from = pop @$ren; - my $to = pop @$ren; + my $from = shift @$ren; + my $to = shift @$ren; unless (-d dirname($to)) { mkpath(dirname($to)); # will die on err } - #print "moving $from $to"; - `mv $from $to`; - die "Error renaming $from $to : $!" if $?; - `git-update-index --remove $from`; - die "Error in git-update-index --remove: $!" if $?; - `git-update-index --add $to`; - die "Error in git-update-index --add: $!" if $?; + print "moving $from $to"; + rename($from, $to) or die "Error renaming '$from' '$to': $!\n"; + system('git-update-index','--remove','--',$from) == 0 or + die "Error in git-update-index --remove: $! $?\n"; + system('git-update-index','--add','--',$to) == 0 or + die "Error in git-update-index --add: $! $?\n"; } } - if (@$mod) { # must be _after_ renames + + if (my $mod = $ps->{modified_files}) { while (@$mod) { my @slice = splice(@$mod, 0, 100); - my $slice = join(' ', @slice); - `git-update-index $slice`; - die "Error in git-update-index: $!" if $?; + system('git-update-index','--',@slice) == 0 or + die "Error in git-update-index: $! $?\n"; } } - + # warn "errors when running git-update-index! $!"; $tree = `git-write-tree`; die "cannot write tree $!" if $?; chomp $tree; - # # Who's your daddy? @@ -464,13 +459,14 @@ foreach my $ps (@psets) { $ENV{GIT_COMMITTER_EMAIL} = $ps->{email}; $ENV{GIT_COMMITTER_DATE} = $ps->{date}; - my ($pid, $commit_rh, $commit_wh); - $commit_rh = 'commit_rh'; - $commit_wh = 'commit_wh'; - - $pid = open2(*READER, *WRITER,'git-commit-tree',$tree,@par) + my $pid = open2(*READER, *WRITER,'git-commit-tree',$tree,@par) or die $!; - print WRITER $logmessage; # write + print WRITER $ps->{summary},"\n"; + print WRITER $ps->{message},"\n"; + + # make it easy to backtrack and figure out which Arch revision this was: + print WRITER 'git-archimport-id: ',$ps->{id},"\n"; + close WRITER; my $commitid = ; # read chomp $commitid; @@ -568,7 +564,9 @@ sub apply_cset { # =for reference -# A log entry looks like +# notes: *-files/-directories keys cannot have spaces, they're always +# pika-escaped. Everything after the first newline +# A log entry looks like: # Revision: moodle-org--moodle--1.3.3--patch-15 # Archive: arch-eduforge@catalyst.net.nz--2004 # Creator: Penny Leach @@ -586,70 +584,85 @@ sub apply_cset { # admin/editor.html backup/lib.php backup/restore.php # New-patches: arch-eduforge@catalyst.net.nz--2004/moodle-org--moodle--1.3.3--patch-15 # Summary: Updating to latest from MOODLE_14_STABLE (1.4.5+) +# summary can be multiline with a leading space just like the above fields # Keywords: # # Updating yadda tadda tadda madda sub parselog { - my $log = shift; - #print $log; - - my (@add, @del, @mod, @ren, @kw, $sum, $msg ); - - if ($log =~ m/(?:\n|^)New-files:(.*?)(?=\n\w)/s ) { - my $files = $1; - @add = split(m/\s+/s, $files); - } - - if ($log =~ m/(?:\n|^)Removed-files:(.*?)(?=\n\w)/s ) { - my $files = $1; - @del = split(m/\s+/s, $files); - } + my ($ps, $log) = @_; + my $key = undef; + + # headers we want that contain filenames: + my %want_headers = ( + new_files => 1, + modified_files => 1, + renamed_files => 1, + renamed_directories => 1, + removed_files => 1, + removed_directories => 1, + ); - if ($log =~ m/(?:\n|^)Modified-files:(.*?)(?=\n\w)/s ) { - my $files = $1; - @mod = split(m/\s+/s, $files); + chomp (@$log); + while ($_ = shift @$log) { + if (/^Continuation-of:\s*(.*)/) { + $ps->{tag} = $1; + $key = undef; + } elsif (/^Summary:\s*(.*)$/ ) { + # summary can be multiline as long as it has a leading space + $ps->{summary} = [ $1 ]; + $key = 'summary'; + } elsif (/^Creator: (.*)\s*<([^\>]+)>/) { + $ps->{author} = $1; + $ps->{email} = $2; + $key = undef; + # any *-files or *-directories can be read here: + } elsif (/^([A-Z][a-z\-]+):\s*(.*)$/) { + my $val = $2; + $key = lc $1; + $key =~ tr/-/_/; # too lazy to quote :P + if ($want_headers{$key}) { + push @{$ps->{$key}}, split(/\s+/, $val); + } else { + $key = undef; + } + } elsif (/^$/) { + last; # remainder of @$log that didn't get shifted off is message + } elsif ($key) { + if (/^\s+(.*)$/) { + if ($key eq 'summary') { + push @{$ps->{$key}}, $1; + } else { # files/directories: + push @{$ps->{$key}}, split(/\s+/, $1); + } + } else { + $key = undef; + } + } } + + # post-processing: + $ps->{summary} = join("\n",@{$ps->{summary}})."\n"; + $ps->{message} = join("\n",@$log); - if ($log =~ m/(?:\n|^)Renamed-files:(.*?)(?=\n\w)/s ) { - my $files = $1; - @ren = split(m/\s+/s, $files); - } - - $sum =''; - if ($log =~ m/^Summary:(.+?)$/m ) { - $sum = $1; - $sum =~ s/^\s+//; - $sum =~ s/\s+$//; - } - - $msg = ''; - if ($log =~ m/\n\n(.+)$/s) { - $msg = $1; - $msg =~ s/^\s+//; - $msg =~ s/\s+$//; - } - - - # cleanup the arrays - foreach my $ref ( (\@add, \@del, \@mod, \@ren) ) { - my @tmp = (); - while (my $t = pop @$ref) { - next unless length ($t); - next if $t =~ m!\{arch\}/!; - next if $t =~ m!\.arch-ids/!; - next if $t =~ m!\.arch-inventory$!; + # skip Arch control files, unescape pika-escaped files + foreach my $k (keys %want_headers) { + next unless (defined $ps->{$k}); + my @tmp; + foreach my $t (@{$ps->{$k}}) { + next unless length ($t); + next if $t =~ m!\{arch\}/!; + next if $t =~ m!\.arch-ids/!; + # should we skip this? + next if $t =~ m!\.arch-inventory$!; # tla cat-archive-log will give us filenames with spaces as file\(sp)name - why? # we can assume that any filename with \ indicates some pika escaping that we want to get rid of. - if ($t =~ /\\/ ){ + if ($t =~ /\\/ ){ $t = (safe_pipe_capture($TLA,'escape','--unescaped',$t))[0]; } - push (@tmp, $t); + push @tmp, $t; } - @$ref = @tmp; + $ps->{$k} = \@tmp if scalar @tmp; } - - #print Dumper [$sum, $msg, \@add, \@del, \@mod, \@ren]; - return ($sum, $msg, \@add, \@del, \@mod, \@ren); } # write/read a tag -- cgit v1.2.3 From 3e525e673849393035a2639e17ff74e616a618b9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:55:04 -0800 Subject: archimport: Add the accurate changeset applyer And make it the default. This includes stats tracking to verbose mode Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 199 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 171 insertions(+), 28 deletions(-) diff --git a/git-archimport.perl b/git-archimport.perl index 8676f35f0f..1cf126181b 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -25,6 +25,9 @@ See man (1) git-archimport for more details. - audit shell-escaping of filenames - hide our private tags somewhere smarter - find a way to make "cat *patches | patch" safe even when patchfiles are missing newlines + - sort and apply patches by graphing ancestry relations instead of just + relying in dates supplied in the changeset itself. + tla ancestry-graph -m could be helpful here... =head1 Devel tricks @@ -66,18 +69,18 @@ my $git_dir = $ENV{"GIT_DIR"} || ".git"; $ENV{"GIT_DIR"} = $git_dir; my $ptag_dir = "$git_dir/archimport/tags"; -our($opt_h,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o); +our($opt_h,$opt_f,$opt_v,$opt_T,$opt_t,$opt_D,$opt_a,$opt_o); sub usage() { print STDERR <= 1 or usage(); @@ -95,6 +98,10 @@ my %reachable = (); # Arch repositories we can access my %unreachable = (); # Arch repositories we can't access :< my @psets = (); # the collection my %psets = (); # the collection, by name +my %stats = ( # Track which strategy we used to import: + get_tag => 0, replay => 0, get_new => 0, get_delta => 0, + simple_changeset => 0, import_or_tag => 0 +); my %rptags = (); # my reverse private tags # to map a SHA1 to a commitid @@ -288,29 +295,69 @@ sub old_style_branchname { *git_branchname = $opt_o ? *old_style_branchname : *tree_dirname; -# process patchsets -foreach my $ps (@psets) { - $ps->{branch} = git_branchname($ps->{id}); - - # - # ensure we have a clean state - # - if (`git-diff-files`) { - die "Unclean tree when about to process $ps->{id} " . - " - did we fail to commit cleanly before?"; - } - die $! if $?; +sub process_patchset_accurate { + my $ps = shift; + + # switch to that branch if we're not already in that branch: + if (-e "$git_dir/refs/heads/$ps->{branch}") { + system('git-checkout','-f',$ps->{branch}) == 0 or die "$! $?\n"; - # - # skip commits already in repo - # - if (ptag($ps->{id})) { - $opt_v && print " * Skipping already imported: $ps->{id}\n"; - next; + # remove any old stuff that got leftover: + my $rm = safe_pipe_capture('git-ls-files','--others','-z'); + rmtree(split(/\0/,$rm)) if $rm; } + + # Apply the import/changeset/merge into the working tree + my $dir = sync_to_ps($ps); + # read the new log entry: + my @commitlog = safe_pipe_capture($TLA,'cat-log','-d',$dir,$ps->{id}); + die "Error in cat-log: $!" if $?; + chomp @commitlog; + + # grab variables we want from the log, new fields get added to $ps: + # (author, date, email, summary, message body ...) + parselog($ps, \@commitlog); + + if ($ps->{id} =~ /--base-0$/ && $ps->{id} ne $psets[0]{id}) { + # this should work when importing continuations + if ($ps->{tag} && (my $branchpoint = eval { ptag($ps->{tag}) })) { + + # find where we are supposed to branch from + system('git-checkout','-f','-b',$ps->{branch}, + $branchpoint) == 0 or die "$! $?\n"; + + # remove any old stuff that got leftover: + my $rm = safe_pipe_capture('git-ls-files','--others','-z'); + rmtree(split(/\0/,$rm)) if $rm; - print " * Starting to work on $ps->{id}\n"; + # If we trust Arch with the fact that this is just + # a tag, and it does not affect the state of the tree + # then we just tag and move on + tag($ps->{id}, $branchpoint); + ptag($ps->{id}, $branchpoint); + print " * Tagged $ps->{id} at $branchpoint\n"; + return 0; + } else { + warn "Tagging from unknown id unsupported\n" if $ps->{tag}; + } + # allow multiple bases/imports here since Arch supports cherry-picks + # from unrelated trees + } + + # update the index with all the changes we got + system('git-ls-files --others -z | '. + 'git-update-index --add -z --stdin') == 0 or die "$! $?\n"; + system('git-ls-files --deleted -z | '. + 'git-update-index --remove -z --stdin') == 0 or die "$! $?\n"; + system('git-ls-files -z | '. + 'git-update-index -z --stdin') == 0 or die "$! $?\n"; + return 1; +} +# the native changeset processing strategy. This is very fast, but +# does not handle permissions or any renames involving directories +sub process_patchset_fast { + my $ps = shift; # # create the branch if needed # @@ -338,7 +385,7 @@ foreach my $ps (@psets) { tag($ps->{id}, $branchpoint); ptag($ps->{id}, $branchpoint); print " * Tagged $ps->{id} at $branchpoint\n"; - next; + return 0; } die $! if $?; } @@ -348,16 +395,17 @@ foreach my $ps (@psets) { # if ($ps->{type} eq 'i' || $ps->{type} eq 't') { apply_import($ps) or die $!; + $stats{import_or_tag}++; $import=0; } elsif ($ps->{type} eq 's') { apply_cset($ps); + $stats{simple_changeset}++; } # # prepare update git's index, based on what arch knows # about the pset, resolve parents, etc # - my $tree; my @commitlog = safe_pipe_capture($TLA,'cat-archive-log',$ps->{id}); die "Error in cat-archive-log: $!" if $?; @@ -404,14 +452,13 @@ foreach my $ps (@psets) { unless (-d dirname($to)) { mkpath(dirname($to)); # will die on err } - print "moving $from $to"; + # print "moving $from $to"; rename($from, $to) or die "Error renaming '$from' '$to': $!\n"; system('git-update-index','--remove','--',$from) == 0 or die "Error in git-update-index --remove: $! $?\n"; system('git-update-index','--add','--',$to) == 0 or die "Error in git-update-index --add: $! $?\n"; } - } if (my $mod = $ps->{modified_files}) { @@ -421,9 +468,46 @@ foreach my $ps (@psets) { die "Error in git-update-index: $! $?\n"; } } + return 1; # we successfully applied the changeset +} + +if ($opt_f) { + print "Will import patchsets using the fast strategy\n", + "Renamed directories and permission changes will be missed\n"; + *process_patchset = *process_patchset_fast; +} else { + print "Using the default (accurate) import strategy.\n", + "Things may be a bit slow\n"; + *process_patchset = *process_patchset_accurate; +} +foreach my $ps (@psets) { + # process patchsets + $ps->{branch} = git_branchname($ps->{id}); + + # + # ensure we have a clean state + # + if (my $dirty = `git-diff-files`) { + die "Unclean tree when about to process $ps->{id} " . + " - did we fail to commit cleanly before?\n$dirty"; + } + die $! if $?; + + # + # skip commits already in repo + # + if (ptag($ps->{id})) { + $opt_v && print " * Skipping already imported: $ps->{id}\n"; + return 0; + } + + print " * Starting to work on $ps->{id}\n"; + + process_patchset($ps) or next; + # warn "errors when running git-update-index! $!"; - $tree = `git-write-tree`; + my $tree = `git-write-tree`; die "cannot write tree $!" if $?; chomp $tree; @@ -494,6 +578,65 @@ foreach my $ps (@psets) { print " + commit $commitid\n"; $opt_v && print " + commit date is $ps->{date} \n"; $opt_v && print " + parents: ",join(' ',@par),"\n"; + if (my $dirty = `git-diff-files`) { + die "22 Unclean tree when about to process $ps->{id} " . + " - did we fail to commit cleanly before?\n$dirty"; + } +} + +if ($opt_v) { + foreach (sort keys %stats) { + print" $_: $stats{$_}\n"; + } +} +exit 0; + +# used by the accurate strategy: +sub sync_to_ps { + my $ps = shift; + my $tree_dir = $tmp.'/'.tree_dirname($ps->{id}); + + $opt_v && print "sync_to_ps($ps->{id}) method: "; + + if (-d $tree_dir) { + if ($ps->{type} eq 't') { + $opt_v && print "get (tag)\n"; + # looks like a tag-only or (worse,) a mixed tags/changeset branch, + # can't rely on replay to work correctly on these + rmtree($tree_dir); + safe_pipe_capture($TLA,'get','--no-pristine',$ps->{id},$tree_dir); + $stats{get_tag}++; + } else { + my $tree_id = arch_tree_id($tree_dir); + if ($ps->{parent_id} && ($ps->{parent_id} eq $tree_id)) { + # the common case (hopefully) + $opt_v && print "replay\n"; + safe_pipe_capture($TLA,'replay','-d',$tree_dir,$ps->{id}); + $stats{replay}++; + } else { + # getting one tree is usually faster than getting two trees + # and applying the delta ... + rmtree($tree_dir); + $opt_v && print "apply-delta\n"; + safe_pipe_capture($TLA,'get','--no-pristine', + $ps->{id},$tree_dir); + $stats{get_delta}++; + } + } + } else { + # new branch work + $opt_v && print "get (new tree)\n"; + safe_pipe_capture($TLA,'get','--no-pristine',$ps->{id},$tree_dir); + $stats{get_new}++; + } + + # added -I flag to rsync since we're going to fast! AIEEEEE!!!! + system('rsync','-aI','--delete','--exclude',$git_dir, +# '--exclude','.arch-inventory', + '--exclude','.arch-ids','--exclude','{arch}', + '--exclude','+*','--exclude',',*', + "$tree_dir/",'./') == 0 or die "Cannot rsync $tree_dir: $! $?"; + return $tree_dir; } sub apply_import { @@ -896,7 +1039,7 @@ sub safe_pipe_capture { @output = (<$child>); close $child or die join(' ',@_).": $! $?"; } else { - exec(@_) or die $?; # exec() can fail the executable can't be found + exec(@_) or die "$! $?"; # exec() can fail the executable can't be found } return wantarray ? @output : join('',@output); } -- cgit v1.2.3 From 6e33101abd82f38393b8f2a137601add845722f7 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:56:31 -0800 Subject: archimport: Fix a bug I introduced in the new log parser This fixes the case (that worked originally in Martin's version) where the only new/modified files are Arch control files. Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-archimport.perl b/git-archimport.perl index 1cf126181b..0080850016 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -790,7 +790,7 @@ sub parselog { # skip Arch control files, unescape pika-escaped files foreach my $k (keys %want_headers) { next unless (defined $ps->{$k}); - my @tmp; + my @tmp = (); foreach my $t (@{$ps->{$k}}) { next unless length ($t); next if $t =~ m!\{arch\}/!; @@ -804,7 +804,7 @@ sub parselog { } push @tmp, $t; } - $ps->{$k} = \@tmp if scalar @tmp; + $ps->{$k} = \@tmp; } } -- cgit v1.2.3 From 10945e006a9567f4da1dac15cfdc1035752c5c5e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Wed, 23 Nov 2005 23:58:16 -0800 Subject: archimport: fix a in new changeset applyer addition Fix a stupid bug I introduced when splitting the accurate and fast changeset appliers. Also, remove an old debugging statement I added Signed-off-by: Eric Wong Signed-off-by: Martin Langhoff --- git-archimport.perl | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/git-archimport.perl b/git-archimport.perl index 0080850016..aab4e38440 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -499,7 +499,7 @@ foreach my $ps (@psets) { # if (ptag($ps->{id})) { $opt_v && print " * Skipping already imported: $ps->{id}\n"; - return 0; + next; } print " * Starting to work on $ps->{id}\n"; @@ -578,10 +578,6 @@ foreach my $ps (@psets) { print " + commit $commitid\n"; $opt_v && print " + commit date is $ps->{date} \n"; $opt_v && print " + parents: ",join(' ',@par),"\n"; - if (my $dirty = `git-diff-files`) { - die "22 Unclean tree when about to process $ps->{id} " . - " - did we fail to commit cleanly before?\n$dirty"; - } } if ($opt_v) { -- cgit v1.2.3 From 024510c8d947be6ae4765840e21a89d5a21271c4 Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Sat, 10 Dec 2005 17:25:24 -0500 Subject: Allow saving an object from a pipe In order to support getting data into git with scripts, this adds a --stdin option to git-hash-object, which will make it read from stdin. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- Documentation/git-hash-object.txt | 5 ++++- cache.h | 1 + hash-object.c | 15 +++++++++++++-- sha1_file.c | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/Documentation/git-hash-object.txt b/Documentation/git-hash-object.txt index db12e926f8..0924931dc1 100644 --- a/Documentation/git-hash-object.txt +++ b/Documentation/git-hash-object.txt @@ -8,7 +8,7 @@ git-hash-object - Computes object ID and optionally creates a blob from a file. SYNOPSIS -------- -'git-hash-object' [-t ] [-w] +'git-hash-object' [-t ] [-w] [--stdin] [--] ... DESCRIPTION ----------- @@ -29,6 +29,9 @@ OPTIONS -w:: Actually write the object into the object database. +--stdin:: + Read the object from standard input instead of from a file. + Author ------ Written by Junio C Hamano diff --git a/cache.h b/cache.h index 86fc25084c..c78d8aea41 100644 --- a/cache.h +++ b/cache.h @@ -144,6 +144,7 @@ extern int ce_match_stat(struct cache_entry *ce, struct stat *st); extern int ce_modified(struct cache_entry *ce, struct stat *st); extern int ce_path_match(const struct cache_entry *ce, const char **pathspec); extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type); +extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object); extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object); extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st); diff --git a/hash-object.c b/hash-object.c index 62279368b8..6502b5b3d1 100644 --- a/hash-object.c +++ b/hash-object.c @@ -21,8 +21,16 @@ static void hash_object(const char *path, const char *type, int write_object) printf("%s\n", sha1_to_hex(sha1)); } +static void hash_stdin(const char *type, int write_object) +{ + unsigned char sha1[20]; + if (index_pipe(sha1, 0, type, write_object)) + die("Unable to add stdin to database"); + printf("%s\n", sha1_to_hex(sha1)); +} + static const char hash_object_usage[] = -"git-hash-object [-t ] [-w] ..."; +"git-hash-object [-t ] [-w] [--stdin] ..."; int main(int argc, char **argv) { @@ -53,9 +61,12 @@ int main(int argc, char **argv) } else if (!strcmp(argv[i], "--help")) usage(hash_object_usage); + else if (!strcmp(argv[i], "--stdin")) { + hash_stdin(type, write_object); + } else die(hash_object_usage); - } + } else { const char *arg = argv[i]; if (0 <= prefix_length) diff --git a/sha1_file.c b/sha1_file.c index 111a71de6b..fa22e9c71a 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1528,6 +1528,40 @@ int has_sha1_file(const unsigned char *sha1) return find_sha1_file(sha1, &st) ? 1 : 0; } +int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object) +{ + unsigned long size = 4096; + char *buf = malloc(size); + int iret, ret; + unsigned long off = 0; + unsigned char hdr[50]; + int hdrlen; + do { + iret = read(fd, buf + off, size - off); + if (iret > 0) { + off += iret; + if (off == size) { + size *= 2; + buf = realloc(buf, size); + } + } + } while (iret > 0); + if (iret < 0) { + free(buf); + return -1; + } + if (!type) + type = "blob"; + if (write_object) + ret = write_sha1_file(buf, off, type, sha1); + else { + write_sha1_file_prepare(buf, off, type, sha1, hdr, &hdrlen); + ret = 0; + } + free(buf); + return ret; +} + int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type) { unsigned long size = st->st_size; -- cgit v1.2.3 From 73ab46d6d03fc38e7b57f7fb731da432d4433268 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 10 Dec 2005 18:36:15 -0800 Subject: t3300: funny name test Add double quote character to the test pattern. Signed-off-by: Junio C Hamano --- t/t3300-funny-names.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/t/t3300-funny-names.sh b/t/t3300-funny-names.sh index 897c378422..6a85d67c57 100755 --- a/t/t3300-funny-names.sh +++ b/t/t3300-funny-names.sh @@ -15,7 +15,7 @@ test "$(uname -o 2>/dev/null)" = Cygwin && exit 0 . ./test-lib.sh p0='no-funny' -p1='tabs and spaces' +p1='tabs ," (dq) and spaces' p2='just space' cat >"$p0" <<\EOF @@ -39,7 +39,7 @@ echo "$t0" >t0 echo 'just space no-funny -"tabs\tand spaces"' >expected +"tabs\t,\" (dq) and spaces"' >expected test_expect_success 'git-ls-files with-funny' \ 'git-update-index --add "$p1" && git-ls-files >current && @@ -47,7 +47,7 @@ test_expect_success 'git-ls-files with-funny' \ echo 'just space no-funny -tabs and spaces' >expected +tabs ," (dq) and spaces' >expected test_expect_success 'git-ls-files -z with-funny' \ 'git-ls-files -z | tr \\0 \\012 >current && diff -u expected current' @@ -57,12 +57,12 @@ echo "$t1" >t1 echo 'just space no-funny -"tabs\tand spaces"' >expected +"tabs\t,\" (dq) and spaces"' >expected test_expect_success 'git-ls-tree with funny' \ 'git-ls-tree -r $t1 | sed -e "s/^[^ ]* //" >current && diff -u expected current' -echo 'A "tabs\tand spaces"' >expected +echo 'A "tabs\t,\" (dq) and spaces"' >expected test_expect_success 'git-diff-index with-funny' \ 'git-diff-index --name-status $t0 >current && diff -u expected current' @@ -72,7 +72,7 @@ test_expect_success 'git-diff-tree with-funny' \ diff -u expected current' echo 'A -tabs and spaces' >expected +tabs ," (dq) and spaces' >expected test_expect_success 'git-diff-index -z with-funny' \ 'git-diff-index -z --name-status $t0 | tr \\0 \\012 >current && diff -u expected current' @@ -81,23 +81,23 @@ test_expect_success 'git-diff-tree -z with-funny' \ 'git-diff-tree -z --name-status $t0 $t1 | tr \\0 \\012 >current && diff -u expected current' -echo 'CNUM no-funny "tabs\tand spaces"' >expected +echo 'CNUM no-funny "tabs\t,\" (dq) and spaces"' >expected test_expect_success 'git-diff-tree -C with-funny' \ 'git-diff-tree -C --find-copies-harder --name-status \ $t0 $t1 | sed -e 's/^C[0-9]*/CNUM/' >current && diff -u expected current' -echo 'RNUM no-funny "tabs\tand spaces"' >expected +echo 'RNUM no-funny "tabs\t,\" (dq) and spaces"' >expected test_expect_success 'git-diff-tree delete with-funny' \ 'git-update-index --force-remove "$p0" && git-diff-index -M --name-status \ $t0 | sed -e 's/^R[0-9]*/RNUM/' >current && diff -u expected current' -echo 'diff --git a/no-funny "b/tabs\tand spaces" +echo 'diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" similarity index NUM% rename from no-funny -rename to "tabs\tand spaces"' >expected +rename to "tabs\t,\" (dq) and spaces"' >expected test_expect_success 'git-diff-tree delete with-funny' \ 'git-diff-index -M -p $t0 | @@ -105,19 +105,19 @@ test_expect_success 'git-diff-tree delete with-funny' \ diff -u expected current' chmod +x "$p1" -echo 'diff --git a/no-funny "b/tabs\tand spaces" +echo 'diff --git a/no-funny "b/tabs\t,\" (dq) and spaces" old mode 100644 new mode 100755 similarity index NUM% rename from no-funny -rename to "tabs\tand spaces"' >expected +rename to "tabs\t,\" (dq) and spaces"' >expected test_expect_success 'git-diff-tree delete with-funny' \ 'git-diff-index -M -p $t0 | sed -e "s/index [0-9]*%/index NUM%/" >current && diff -u expected current' -echo >expected ' "tabs\tand spaces" +echo >expected ' "tabs\t,\" (dq) and spaces" 1 files changed, 0 insertions(+), 0 deletions(-)' test_expect_success 'git-diff-tree rename with-funny applied' \ 'git-diff-index -M -p $t0 | @@ -125,7 +125,7 @@ test_expect_success 'git-diff-tree rename with-funny applied' \ diff -u expected current' echo >expected ' no-funny - "tabs\tand spaces" + "tabs\t,\" (dq) and spaces" 2 files changed, 3 insertions(+), 3 deletions(-)' test_expect_success 'git-diff-tree delete with-funny applied' \ -- cgit v1.2.3 From eea420693befc2f876079a8a4585ea8ebf07c047 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 10 Dec 2005 20:55:32 -0800 Subject: t0000: catch trivial pilot errors. People seem to be getting test failure from t6021 not becuase git is faulty but because they forgot to install "merge". Check this and other trivial pilot errors in the first test. Signed-off-by: Junio C Hamano --- t/t0000-basic.sh | 29 +++++++++++++++++++++++++++++ t/test-lib.sh | 9 +++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 22bdacaf78..bc3e711a52 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -17,8 +17,37 @@ IDs. When object ID computation changes, like in the previous case of swapping compression and hashing order, the person who is making the modification *should* take notice and update the test vectors here. ' + +################################################################ +# It appears that people are getting bitten by not installing +# 'merge' (usually part of RCS package in binary distributions) +# or have too old python without subprocess. Check them and error +# out before running any tests. Also catch the bogosity of trying +# to run tests without building while we are at it. + +../git >/dev/null +if test $? != 1 +then + echo >&2 'You do not seem to have built git yet.' + exit 1 +fi + +merge >/dev/null 2>/dev/null +if test $? == 127 +then + echo >&2 'You do not seem to have "merge" installed. +Please check INSTALL document.' + exit 1 +fi + . ./test-lib.sh +"$PYTHON" -c 'import subprocess' || { + echo >&2 'Your python seem to lack "subprocess" module. +Please check INSTALL document.' + exit 1 +} + ################################################################ # init-db has been done in an empty repository. # make sure it is empty. diff --git a/t/test-lib.sh b/t/test-lib.sh index 447d9e2517..2819bef1c4 100755 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -179,11 +179,16 @@ export PATH GIT_EXEC_PATH PYTHON=`sed -e '1{ s/^#!// q -}' ../git-merge-recursive` && +}' ../git-merge-recursive` || { + error "You haven't built things yet, have you?" +} "$PYTHON" -c 'import subprocess' 2>/dev/null || { PYTHONPATH=$(pwd)/../compat export PYTHONPATH } +test -d ../templates/blt || { + error "You haven't built things yet, have you?" +} # Test repository test=trash @@ -191,6 +196,6 @@ rm -fr "$test" mkdir "$test" cd "$test" "$GIT_EXEC_PATH/git" init-db --template=../../templates/blt/ 2>/dev/null || -error "cannot run git init-db" +error "cannot run git init-db -- have you built things yet?" mv .git/hooks .git/hooks-disabled -- cgit v1.2.3 From 7564577a6c05a1153ddb94cbe68e75c391b52f20 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 10 Dec 2005 22:22:35 -0800 Subject: format-patch: use same number of digits in numbers This would help sorting by subject in MUA work saner even though MUA is too dumb to attempt sorting numbered subjects sanely. Signed-off-by: Junio C Hamano --- git-format-patch.sh | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/git-format-patch.sh b/git-format-patch.sh index 1eebe857c0..921feee59c 100755 --- a/git-format-patch.sh +++ b/git-format-patch.sh @@ -254,6 +254,15 @@ Date: '"$ad" } total=`wc -l <$series | tr -dc "[0-9]"` +case "$total,$numbered" in +1,*) + numfmt='' ;; +*,t) + numfmt=`echo "$total" | wc -c` + numfmt=$(($numfmt-1)) + numfmt=" %0${numfmt}d/$total" +esac + i=1 while read commit do @@ -262,10 +271,7 @@ do case "$numbered" in '') num= ;; *) - case $total in - 1) num= ;; - *) num=' '`printf "%d/%d" $i $total` ;; - esac + num=`printf "$numfmt" $i` ;; esac file=`printf '%04d-%stxt' $i "$title"` -- cgit v1.2.3 From 28e77a81647584bfbe112f19e12e9952ab0b2fab Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 10 Dec 2005 22:05:01 -0800 Subject: merge-recursive: leave unmerged entries in the index. This does two things. - When one branch renamed and the other branch did not, the resulting half-merged file in the working tree used to swap branches around and showed as if renaming side was "ours". This was confusing and inconsistent (even though the conflict markers were marked with branch names, it was not a good enough excuse). This changes the order of arguments to mergeFile in such a case to make sure we always see "our" change between <<< and ===, and "their" change between === and >>>. - When both branches renamed to the same path, and when one branch renamed and the other branch did not, we attempt mergeFile. When this automerge conflicted, we used to collapse the index. Now we use update-index --index-info to inject higher stage entries to leave the index in unmerged state for these two cases. What this still does _not_ do is to inject unmerged state into the index when the structural changes conflict. I have not thought things through what to do in each case yet, but the cases this commit cover are the most common ones, so this would be a good start. Signed-off-by: Junio C Hamano --- git-merge-recursive.py | 54 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/git-merge-recursive.py b/git-merge-recursive.py index b7fb0961e0..767b13c927 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -280,6 +280,22 @@ def updateFileExt(sha, mode, path, updateCache, updateWd): runProgram(['git-update-index', '--add', '--cacheinfo', '0%o' % mode, sha, path]) +def setIndexStages(path, + oSHA1, oMode, + aSHA1, aMode, + bSHA1, bMode): + prog = ['git-update-index', '-z', '--index-info'] + proc = subprocess.Popen(prog, stdin=subprocess.PIPE) + pipe = proc.stdin + # Clear stages first. + pipe.write("0 " + ("0" * 40) + "\t" + path + "\0") + # Set stages + pipe.write("%o %s %d\t%s\0" % (oMode, oSHA1, 1, path)) + pipe.write("%o %s %d\t%s\0" % (aMode, aSHA1, 2, path)) + pipe.write("%o %s %d\t%s\0" % (bMode, bSHA1, 3, path)) + pipe.close() + proc.wait() + def removeFile(clean, path): updateCache = cacheOnly or clean updateWd = not cacheOnly @@ -590,6 +606,8 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): else: dstName2 = ren1.dstName + # NEEDSWORK: place dstNameA at stage 2 and dstNameB at stage 3 + # What about other stages??? updateFile(False, ren1.dstSha, ren1.dstMode, dstName1) updateFile(False, ren2.dstSha, ren2.dstMode, dstName2) else: @@ -611,8 +629,11 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): cleanMerge = False if not cacheOnly: - updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName, - updateCache=True, updateWd=False) + setIndexStages(ren1.dstName, + ren1.srcSha, ren1.srcMode, + ren1.dstSha, ren1.dstMode, + ren2.dstSha, ren2.dstMode) + updateFile(clean, resSha, resMode, ren1.dstName) else: # Renamed in 1, maybe changed in 2 @@ -672,11 +693,24 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): tryMerge = True if tryMerge: + + oName, oSHA1, oMode = ren1.srcName, ren1.srcSha, ren1.srcMode + aName, bName = ren1.dstName, ren1.srcName + aSHA1, bSHA1 = ren1.dstSha, srcShaOtherBranch + aMode, bMode = ren1.dstMode, srcModeOtherBranch + aBranch, bBranch = branchName1, branchName2 + + if renamesA != renames1: + aName, bName = bName, aName + aSHA1, bSHA1 = bSHA1, aSHA1 + aMode, bMode = bMode, aMode + aBranch, bBranch = bBranch, aBranch + [resSha, resMode, clean, merge] = \ - mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode, - ren1.dstName, ren1.dstSha, ren1.dstMode, - ren1.srcName, srcShaOtherBranch, srcModeOtherBranch, - branchName1, branchName2) + mergeFile(oName, oSHA1, oMode, + aName, aSHA1, aMode, + bName, bSHA1, bMode, + aBranch, bBranch); if merge or not clean: output('Renaming', fmtRename(ren1.srcName, ren1.dstName)) @@ -690,8 +724,12 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): cleanMerge = False if not cacheOnly: - updateFileExt(ren1.dstSha, ren1.dstMode, ren1.dstName, - updateCache=True, updateWd=False) + # Stuff stage1/2/3 + setIndexStages(ren1.dstName, + oSHA1, oMode, + aSHA1, aMode, + bSHA1, bMode) + updateFile(clean, resSha, resMode, ren1.dstName) return cleanMerge -- cgit v1.2.3 From 157dc07368faf6537af1d2ce676a4f2dda2f71a6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 11 Dec 2005 01:55:52 -0800 Subject: merge-recursive: cleanup setIndexStages Fredrik points out there is a useful wrapper runProgram() used everywhere that we can use to feed input into subprocess. Use it to catch errors from the subprocess; it is a good cleanup as well. Signed-off-by: Junio C Hamano --- git-merge-recursive.py | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/git-merge-recursive.py b/git-merge-recursive.py index 767b13c927..f1320a6958 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -284,17 +284,11 @@ def setIndexStages(path, oSHA1, oMode, aSHA1, aMode, bSHA1, bMode): - prog = ['git-update-index', '-z', '--index-info'] - proc = subprocess.Popen(prog, stdin=subprocess.PIPE) - pipe = proc.stdin - # Clear stages first. - pipe.write("0 " + ("0" * 40) + "\t" + path + "\0") - # Set stages - pipe.write("%o %s %d\t%s\0" % (oMode, oSHA1, 1, path)) - pipe.write("%o %s %d\t%s\0" % (aMode, aSHA1, 2, path)) - pipe.write("%o %s %d\t%s\0" % (bMode, bSHA1, 3, path)) - pipe.close() - proc.wait() + runProgram(['git-update-index', '-z', '--index-info'], + input="0 " + ("0" * 40) + "\t" + path + "\0" + \ + "%o %s %d\t%s\0" % (oMode, oSHA1, 1, path) + \ + "%o %s %d\t%s\0" % (aMode, aSHA1, 2, path) + \ + "%o %s %d\t%s\0" % (bMode, bSHA1, 3, path)) def removeFile(clean, path): updateCache = cacheOnly or clean @@ -724,7 +718,6 @@ def processRenames(renamesA, renamesB, branchNameA, branchNameB): cleanMerge = False if not cacheOnly: - # Stuff stage1/2/3 setIndexStages(ren1.dstName, oSHA1, oMode, aSHA1, aMode, -- cgit v1.2.3 From b825e6ff5d003db8efd1ed43cdbbb9d637df0a0c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 11 Dec 2005 12:44:46 -0800 Subject: t/t6022: a new test for renaming merge. This adds a couple of tests to cover the following renaming merge cases: - one side renames and the other side does not, with and without content conflicts. - both side rename to the same path, with and without content conflicts. The test setup also prepares a case in which both side rename to different destination, but currently the code collapses these destination paths and removes the original path, which may be wrong. The outcome of this case is not checked by the tests in this round. Signed-off-by: Junio C Hamano --- t/t6022-merge-rename.sh | 164 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100755 t/t6022-merge-rename.sh diff --git a/t/t6022-merge-rename.sh b/t/t6022-merge-rename.sh new file mode 100755 index 0000000000..153b9e49f2 --- /dev/null +++ b/t/t6022-merge-rename.sh @@ -0,0 +1,164 @@ +#!/bin/sh + +test_description='Merge-recursive merging renames' +. ./test-lib.sh + +test_expect_success setup \ +' +cat >A <<\EOF && +a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +c cccccccccccccccccccccccccccccccccccccccccccccccc +d dddddddddddddddddddddddddddddddddddddddddddddddd +e eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee +f ffffffffffffffffffffffffffffffffffffffffffffffff +g gggggggggggggggggggggggggggggggggggggggggggggggg +h hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh +i iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii +j jjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjjj +k kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk +l llllllllllllllllllllllllllllllllllllllllllllllll +m mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm +n nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn +o oooooooooooooooooooooooooooooooooooooooooooooooo +EOF + +cat >M <<\EOF && +A AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +B BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB +C CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC +D DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD +E EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE +F FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +G GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGG +H HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH +I IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII +J JJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJ +K KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK +L LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL +M MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +N NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN +O OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO +EOF + +git add A M && +git commit -m initial && +git branch white && +git branch red && +git branch blue && + +sed -e "/^g /s/.*/g : master changes a line/" A+ && +mv A+ A && +git commit -a -m "master updates A" && + +git checkout white && +sed -e "/^g /s/.*/g : white changes a line/" B && +sed -e "/^G /s/.*/G : colored branch changes a line/" N && +rm -f A M && +git update-index --add --remove A B M N && +git commit -m "white renames A->B, M->N" && + +git checkout red && +sed -e "/^g /s/.*/g : red changes a line/" B && +sed -e "/^G /s/.*/G : colored branch changes a line/" N && +rm -f A M && +git update-index --add --remove A B M N && +git commit -m "red renames A->B, M->N" && + +git checkout blue && +sed -e "/^g /s/.*/g : blue changes a line/" C && +sed -e "/^G /s/.*/G : colored branch changes a line/" N && +rm -f A M && +git update-index --add --remove A C M N && +git commit -m "blue renames A->C, M->N" && + +git checkout master' + +test_expect_success 'pull renaming branch into unrenaming one' \ +' + git show-branch + git pull . white && { + echo "BAD: should have conflicted" + exit 1 + } + git ls-files -s + test "$(git ls-files -u B | wc -l)" -eq 3 || { + echo "BAD: should have left stages for B" + exit 1 + } + test "$(git ls-files -s N | wc -l)" -eq 1 || { + echo "BAD: should have merged N" + exit 1 + } + sed -ne "/^g/{ + p + q + }" B | grep master || { + echo "BAD: should have listed our change first" + exit 1 + } + test "$(git diff white N | wc -l)" -eq 0 || { + echo "BAD: should have taken colored branch" + exit 1 + } +' + +test_expect_success 'pull renaming branch into another renaming one' \ +' + git reset --hard + git checkout red + git pull . white && { + echo "BAD: should have conflicted" + exit 1 + } + test "$(git ls-files -u B | wc -l)" -eq 3 || { + echo "BAD: should have left stages" + exit 1 + } + test "$(git ls-files -s N | wc -l)" -eq 1 || { + echo "BAD: should have merged N" + exit 1 + } + sed -ne "/^g/{ + p + q + }" B | grep red || { + echo "BAD: should have listed our change first" + exit 1 + } + test "$(git diff white N | wc -l)" -eq 0 || { + echo "BAD: should have taken colored branch" + exit 1 + } +' + +test_expect_success 'pull unrenaming branch into renaming one' \ +' + git reset --hard + git show-branch + git pull . master && { + echo "BAD: should have conflicted" + exit 1 + } + test "$(git ls-files -u B | wc -l)" -eq 3 || { + echo "BAD: should have left stages" + exit 1 + } + test "$(git ls-files -s N | wc -l)" -eq 1 || { + echo "BAD: should have merged N" + exit 1 + } + sed -ne "/^g/{ + p + q + }" B | grep red || { + echo "BAD: should have listed our change first" + exit 1 + } + test "$(git diff white N | wc -l)" -eq 0 || { + echo "BAD: should have taken colored branch" + exit 1 + } +' + +test_done -- cgit v1.2.3