From e7a0919115ee15b21a557609c2268e24497c1059 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 23 Feb 2007 12:36:34 -0800 Subject: [PATCH 001/130] [PATCH] gitk: bind key to Update (reread commits) I chose because it's also the key to reload the current page in web browsers such as Konqueror and Firefox, so users are more likely to be familiar with it. Signed-off-by: Eric Wong Signed-off-by: Paul Mackerras --- gitk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gitk b/gitk index 9ddff3e7f7..1cd2a8f528 100755 --- a/gitk +++ b/gitk @@ -720,6 +720,7 @@ proc makewindow {} { bindkey {findnext 0} bindkey ? findprev bindkey f nextfile + bindkey updatecommits bind . doquit bind . dofind bind . {findnext 0} @@ -985,6 +986,7 @@ f Scroll diff view to next file Increase font size Decrease font size Decrease font size + Update } \ -justify left -bg white -border 2 -relief sunken pack $w.m -side top -fill both From 0053e902b4f777ba454b62263d3695e5292b1559 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 13 Mar 2007 01:57:22 -0700 Subject: [PATCH 002/130] git-log --first-parent: show only the first parent log If your development history does not have fast-forward merges, i.e. the "first parent" of commits in your history are special than other parents, this option gives a better overview of the evolution of a particular branch. Signed-off-by: Junio C Hamano --- revision.c | 14 ++++++++++---- revision.h | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/revision.c b/revision.c index 3c2eb125e6..8afc196847 100644 --- a/revision.c +++ b/revision.c @@ -350,6 +350,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st { struct commit_list *parent = commit->parents; unsigned left_flag; + int add, rest; if (commit->object.flags & ADDED) return; @@ -395,18 +396,19 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st return; left_flag = (commit->object.flags & SYMMETRIC_LEFT); - parent = commit->parents; - while (parent) { + + rest = !revs->first_parent_only; + for (parent = commit->parents, add = 1; parent; add = rest) { struct commit *p = parent->item; parent = parent->next; - parse_commit(p); p->object.flags |= left_flag; if (p->object.flags & SEEN) continue; p->object.flags |= SEEN; - insert_by_date(p, list); + if (add) + insert_by_date(p, list); } } @@ -836,6 +838,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch handle_all(revs, flags); continue; } + if (!strcmp(arg, "--first-parent")) { + revs->first_parent_only = 1; + continue; + } if (!strcmp(arg, "--reflog")) { handle_reflog(revs, flags); continue; diff --git a/revision.h b/revision.h index 6ae39e6bec..55e6b531ce 100644 --- a/revision.h +++ b/revision.h @@ -46,7 +46,8 @@ struct rev_info { boundary:2, left_right:1, parents:1, - reverse:1; + reverse:1, + first_parent_only:1; /* Diff flags */ unsigned int diff:1, From 0a3985dcfbab7359e5b5e198061d03df56c4055c Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 16 Mar 2007 11:45:29 -0400 Subject: [PATCH 003/130] user-manual: run xsltproc without --nonet option The --nonet option prevents xsltproc from going to the network to find anything. But it always tries to find them locally first, so for a user with the necessary docbook stylesheets installed the build will work just fine without xsltproc attempting to use the network; all --nonet does is make it fail rather than falling back on that. That doesn't seem particularly helpful. Signed-off-by: "J. Bruce Fields" --- Documentation/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Makefile b/Documentation/Makefile index 7c1c9e1918..48d41c5729 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -106,7 +106,7 @@ user-manual.xml: user-manual.txt user-manual.conf $(ASCIIDOC) -b docbook -d book $< XSLT = http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl -XSLTOPTS = --nonet --xinclude --stringparam html.stylesheet docbook-xsl.css +XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css user-manual.html: user-manual.xml xsltproc $(XSLTOPTS) -o $@ $(XSLT) $< From 21f13ee203b0dfe5bd9fdd18897cc11343f09ef7 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sun, 18 Mar 2007 18:39:56 +0100 Subject: [PATCH 004/130] user-manual.txt: fix a tiny typo. "file patch" was doubtless intended to be "file path", but "directory name" is clearer. Signed-off-by: Jim Meyering Signed-off-by: "J. Bruce Fields" --- Documentation/user-manual.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 0919574fb4..773f65ef83 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1698,7 +1698,7 @@ If you and maintainer both have accounts on the same machine, then then you can just pull changes from each other's repositories directly; note that all of the commands (gitlink:git-clone[1], git-fetch[1], git-pull[1], etc.) that accept a URL as an argument -will also accept a local file patch; so, for example, you can +will also accept a local directory name; so, for example, you can use ------------------------------------------------- From 06e7ea37875e4ee4a0ada701d52e2466f344c0f3 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sat, 17 Mar 2007 20:40:13 -0400 Subject: [PATCH 005/130] user-manual: Use def_ instead of ref_ for glossary references. I'd like to start using references to the glossary in the user manual. The "ref_" prefix for these references seems a little generic; so replace with "def_". Signed-off-by: "J. Bruce Fields" --- Documentation/sort_glossary.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/sort_glossary.pl b/Documentation/sort_glossary.pl index 05dc7b2c7b..4ae6290368 100644 --- a/Documentation/sort_glossary.pl +++ b/Documentation/sort_glossary.pl @@ -50,8 +50,8 @@ This list is sorted alphabetically: @keys=sort {uc($a) cmp uc($b)} keys %terms; $pattern='(\b(?>";/eg; - print '[[ref_'.no_spaces($key).']]'.$key."::\n" + $terms{$key}=~s/$pattern/sprintf "<>";/eg; + print '[[def_'.no_spaces($key).']]'.$key."::\n" .format_tab_80($terms{$key})."\n"; } From f562e6f3169f652dd9e840286e43d9e8ca45cf14 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sun, 18 Mar 2007 17:02:37 -0400 Subject: [PATCH 006/130] glossary: stop generating automatically The sort_glossary.pl script sorts the glossary, checks for duplicates, and automatically adds cross-references. But it's not so hard to do all that by hand, and sometimes the automatic cross-references are a little wrong; so let's run the script one last time and check in its output. Note: to make the output fit better into the user manual I also deleted the acknowledgements at the end, which was maybe a little rude; feel free to object and I can find a different solution. Cc: Johannes Schindelin Signed-off-by: "J. Bruce Fields" --- Documentation/Makefile | 8 +- Documentation/glossary.txt | 620 ++++++++++++++++++--------------- Documentation/sort_glossary.pl | 69 ---- Documentation/user-manual.txt | 3 - 4 files changed, 332 insertions(+), 368 deletions(-) delete mode 100644 Documentation/sort_glossary.pl diff --git a/Documentation/Makefile b/Documentation/Makefile index 48d41c5729..7db3fb992f 100644 --- a/Documentation/Makefile +++ b/Documentation/Makefile @@ -16,8 +16,9 @@ ARTICLES += repository-layout ARTICLES += hooks ARTICLES += everyday ARTICLES += git-tools +ARTICLES += glossary # with their own formatting rules. -SP_ARTICLES = glossary howto/revert-branch-rebase user-manual +SP_ARTICLES = howto/revert-branch-rebase user-manual DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) @@ -111,11 +112,6 @@ XSLTOPTS = --xinclude --stringparam html.stylesheet docbook-xsl.css user-manual.html: user-manual.xml xsltproc $(XSLTOPTS) -o $@ $(XSLT) $< -glossary.html : glossary.txt sort_glossary.pl - cat $< | \ - perl sort_glossary.pl | \ - $(ASCIIDOC) -b xhtml11 - > glossary.html - howto-index.txt: howto-index.sh $(wildcard howto/*.txt) rm -f $@+ $@ sh ./howto-index.sh $(wildcard howto/*.txt) >$@+ diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index 9f446241e2..82e17db0c0 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -1,365 +1,405 @@ -alternate object database:: - Via the alternates mechanism, a repository can inherit part of its - object database from another object database, which is called - "alternate". +GIT Glossary +============ -bare repository:: - A bare repository is normally an appropriately named - directory with a `.git` suffix that does not have a - locally checked-out copy of any of the files under revision - control. That is, all of the `git` administrative and - control files that would normally be present in the - hidden `.git` sub-directory are directly present in - the `repository.git` directory instead, and no other files - are present and checked out. Usually publishers of public - repositories make bare repositories available. +[[def_alternate_object_database]]alternate object database:: + Via the alternates mechanism, a <> can + inherit part of its <> from another + <>, which is called "alternate". -blob object:: - Untyped object, e.g. the contents of a file. +[[def_bare_repository]]bare repository:: + A <> is normally an appropriately + named <> with a `.git` suffix that does not + have a locally checked-out copy of any of the files under + <> control. That is, all of the `git` + administrative and control files that would normally be present in the + hidden `.git` sub-directory are directly present in the + `<>.git` <> instead, + and no other files are present and checked out. Usually publishers of + public repositories make bare repositories available. -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/`. +[[def_blob_object]]blob object:: + Untyped <>, e.g. the contents of a file. -cache:: - Obsolete for: index. +[[def_branch]]branch:: + A non-cyclical graph of revisions, i.e. the complete history of a + particular <>, which is called the + <> <>. The <> heads + are stored in `$GIT_DIR/refs/heads/`. -chain:: - A list of objects, where each object in the list contains a - reference to its successor (for example, the successor of a commit - could be one of its parents). +[[def_cache]]cache:: + Obsolete for: <>. -changeset:: - BitKeeper/cvsps speak for "commit". Since git does not store - changes, but states, it really does not make sense to use - the term "changesets" with git. +[[def_chain]]chain:: + A list of objects, where each <> in the list contains + a reference to its successor (for example, the successor of a + <> could be one of its parents). -checkout:: - The action of updating the working tree to a revision which was - stored in the object database. +[[def_changeset]]changeset:: + BitKeeper/cvsps speak for "<>". Since git does not + store changes, but states, it really does not make sense to use the term + "changesets" with git. -cherry-picking:: - In SCM jargon, "cherry pick" means to choose a subset of - changes out of a series of changes (typically commits) - and record them as a new series of changes on top of - different codebase. In GIT, this is performed by - "git cherry-pick" command to extract the change - introduced by an existing commit and to record it based - on the tip of the current branch as a new commit. +[[def_checkout]]checkout:: + The action of updating the <> to a + <> which was stored in the + <>. -clean:: - A working tree is clean, if it corresponds to the revision - referenced by the current head. Also see "dirty". +[[def_cherry-picking]]cherry-picking:: + In <> jargon, "cherry pick" means to choose a subset of + changes out of a series of changes (typically commits) and record them + as a new series of changes on top of different codebase. In GIT, this is + performed by "git cherry-pick" command to extract the change introduced + by an existing <> and to record it based on the tip + of the current <> as a new <>. -commit:: - As a verb: The action of storing the current state of the index in the - object database. The result is a revision. - As a noun: Short hand for commit object. +[[def_clean]]clean:: + A <> is <>, if it + corresponds to the <> referenced by the current + <>. Also see "<>". -commit object:: - An object which contains the information about a particular - revision, such as parents, committer, author, date and the - tree object which corresponds to the top directory of the - stored revision. +[[def_commit]]commit:: + As a verb: The action of storing the current state of the + <> in the <>. The + result is a <>. As a noun: Short hand for + <>. -core git:: - Fundamental data structures and utilities of git. Exposes only - limited source code management tools. +[[def_commit_object]]commit object:: + An <> which contains the information about a + particular <>, such as parents, committer, + author, date and the <> which corresponds + to the top <> of the stored + <>. -DAG:: - Directed acyclic graph. The commit objects form a directed acyclic - graph, because they have parents (directed), and the graph of commit - objects is acyclic (there is no chain which begins and ends with the - same object). +[[def_core_git]]core git:: + Fundamental data structures and utilities of git. Exposes only limited + source code management tools. -dangling object:: - An unreachable object which is not reachable even from other - unreachable objects; a dangling object has no references to it - from any reference or object in the repository. +[[def_DAG]]DAG:: + Directed acyclic graph. The <> objects form a + directed acyclic graph, because they have parents (directed), and the + graph of <> objects is acyclic (there is no + <> which begins and ends with the same + <>). -dircache:: +[[def_dangling_object]]dangling object:: + An <> which is not + <> even from other unreachable objects; a + <> has no references to it from any + reference or <> in the <>. + +[[def_dircache]]dircache:: You are *waaaaay* behind. -dirty:: - A working tree is said to be dirty if it contains modifications - which have not been committed to the current branch. - -directory:: +[[def_directory]]directory:: The list you get with "ls" :-) -ent:: - Favorite synonym to "tree-ish" by some total geeks. See +[[def_dirty]]dirty:: + A <> is said to be <> if + it contains modifications which have not been committed to the current + <>. + +[[def_ent]]ent:: + Favorite synonym to "<>" by some total geeks. See `http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth - explanation. Avoid this term, not to confuse people. + explanation. Avoid this term, not to confuse people. -fast forward:: - A fast-forward is a special type of merge where you have - a revision and you are "merging" another branch's changes - that happen to be a descendant of what you have. - In such these cases, you do not make a new merge commit but - instead just update to his revision. This will happen - frequently on a tracking branch of a remote repository. +[[def_fast_forward]]fast forward:: + A fast-forward is a special type of <> where you have a + <> and you are "merging" another + <>'s changes that happen to be a descendant of what + you have. In such these cases, you do not make a new <> + <> but instead just update to his + <>. This will happen frequently on a + <> of a remote + <>. -fetch:: - Fetching a branch means to get the branch's head ref from a - remote repository, to find out which objects are missing from - the local object database, and to get them, too. +[[def_fetch]]fetch:: + Fetching a <> means to get the + <>'s <> from a remote + <>, to find out which objects are missing + from the local <>, and to get them, + too. -file system:: - Linus Torvalds originally designed git to be a user space file - system, i.e. the infrastructure to hold files and directories. - That ensured the efficiency and speed of git. +[[def_file_system]]file system:: + Linus Torvalds originally designed git to be a user space file system, + i.e. the infrastructure to hold files and directories. That ensured the + efficiency and speed of git. -git archive:: - Synonym for repository (for arch people). +[[def_git_archive]]git archive:: + Synonym for <> (for arch people). -grafts:: - Grafts enables two otherwise different lines of development to be - joined together by recording fake ancestry information for commits. - This way you can make git pretend the set of parents a commit - has is different from what was recorded when the commit was created. - Configured via the `.git/info/grafts` file. +[[def_grafts]]grafts:: + Grafts enables two otherwise different lines of development to be joined + together by recording fake ancestry information for commits. This way + you can make git pretend the set of parents a <> has + is different from what was recorded when the <> was + created. Configured via the `.git/info/<>` file. -hash:: - In git's context, synonym to object name. +[[def_hash]]hash:: + In git's context, synonym to <>. -head:: - The top of a branch. It contains a ref to the corresponding - commit object. +[[def_head]]head:: + The top of a <>. It contains a <> to the + corresponding <>. -head ref:: - A ref pointing to a head. Often, this is abbreviated to "head". - Head refs are stored in `$GIT_DIR/refs/heads/`. +[[def_head_ref]]head ref:: + A <> pointing to a <>. Often, this is + abbreviated to "<>". Head refs are stored in + `$GIT_DIR/refs/heads/`. -hook:: - During the normal execution of several git commands, - call-outs are made to optional scripts that allow - a developer to add functionality or checking. - Typically, the hooks allow for a command to be pre-verified - and potentially aborted, and allow for a post-notification - after the operation is done. - The hook scripts are found in the `$GIT_DIR/hooks/` directory, - and are enabled by simply making them executable. +[[def_hook]]hook:: + During the normal execution of several git commands, call-outs are made + to optional scripts that allow a developer to add functionality or + checking. Typically, the hooks allow for a command to be pre-verified + and potentially aborted, and allow for a post-notification after the + operation is done. The <> scripts are found in the + `$GIT_DIR/hooks/` <>, and are enabled by simply + making them executable. -index:: - A collection of files with stat information, whose contents are - stored as objects. The index is a stored version of your working - tree. Truth be told, it can also contain a second, and even a third - version of a working tree, which are used when merging. +[[def_index]]index:: + A collection of files with stat information, whose contents are stored + as objects. The <> is a stored version of your working + <>. Truth be told, it can also contain a second, and even + a third version of a <>, which are used + when merging. -index entry:: - The information regarding a particular file, stored in the index. - An index entry can be unmerged, if a merge was started, but not - yet finished (i.e. if the index contains multiple versions of - that file). +[[def_index_entry]]index entry:: + The information regarding a particular file, stored in the + <>. An <> can be unmerged, + if a <> was started, but not yet finished (i.e. if the + <> contains multiple versions of that file). -master:: - The default development branch. Whenever you create a git - repository, a branch named "master" is created, and becomes - the active branch. In most cases, this contains the local +[[def_master]]master:: + The default development <>. Whenever you create a git + <>, a <> named + "<>" is created, and becomes the active + <>. In most cases, this contains the local development, though that is purely conventional and not required. -merge:: - To merge branches means to try to accumulate the changes since a - common ancestor and apply them to the first branch. An automatic - merge uses heuristics to accomplish that. Evidently, an automatic - merge can fail. +[[def_merge]]merge:: + To <> branches means to try to accumulate the changes + since a common ancestor and apply them to the first + <>. An automatic <> uses heuristics + to accomplish that. Evidently, an automatic <> can + fail. -object:: - The unit of storage in git. It is uniquely identified by - the SHA1 of its contents. Consequently, an object can not - be changed. +[[def_object]]object:: + The unit of storage in git. It is uniquely identified by the + <> of its contents. Consequently, an + <> can not be changed. -object database:: - Stores a set of "objects", and an individual object is identified - by its object name. The objects usually live in `$GIT_DIR/objects/`. +[[def_object_database]]object database:: + Stores a set of "objects", and an individual <> is + identified by its <>. The objects usually + live in `$GIT_DIR/objects/`. -object identifier:: - Synonym for object name. +[[def_object_identifier]]object identifier:: + Synonym for <>. -object name:: - The unique identifier of an object. The hash of the object's contents - using the Secure Hash Algorithm 1 and usually represented by the 40 - character hexadecimal encoding of the hash of the object (possibly - followed by a white space). +[[def_object_name]]object name:: + The unique identifier of an <>. The <> + of the <>'s contents using the Secure Hash Algorithm + 1 and usually represented by the 40 character hexadecimal encoding of + the <> of the <> (possibly followed by + a white space). -object type:: - One of the identifiers "commit","tree","tag" and "blob" describing - the type of an object. +[[def_object_type]]object type:: + One of the identifiers + "<>","<>","<>" and "blob" + describing the type of an <>. -octopus:: - To merge more than two branches. Also denotes an intelligent - predator. +[[def_octopus]]octopus:: + To <> more than two branches. Also denotes an + intelligent predator. -origin:: - The default upstream repository. Most projects have at - least one upstream project which they track. By default - 'origin' is used for that purpose. New upstream updates +[[def_origin]]origin:: + The default upstream <>. Most projects have + at least one upstream project which they track. By default + '<>' is used for that purpose. New upstream updates will be fetched into remote tracking branches named - origin/name-of-upstream-branch, which you can see using - "git branch -r". + <>/name-of-upstream-branch, which you can see using + "git <> -r". -pack:: - A set of objects which have been compressed into one file (to save - space or to transmit them efficiently). +[[def_pack]]pack:: + A set of objects which have been compressed into one file (to save space + or to transmit them efficiently). -pack index:: +[[def_pack_index]]pack index:: The list of identifiers, and other information, of the objects in a - pack, to assist in efficiently accessing the contents of a pack. + <>, to assist in efficiently accessing the contents of a + <>. -parent:: - A commit object contains a (possibly empty) list of the logical - predecessor(s) in the line of development, i.e. its parents. +[[def_parent]]parent:: + A <> contains a (possibly empty) list + of the logical predecessor(s) in the line of development, i.e. its + parents. -pickaxe:: - The term pickaxe refers to an option to the diffcore routines - that help select changes that add or delete a given text string. - With the --pickaxe-all option, it can be used to view the - full changeset that introduced or removed, say, a particular - line of text. See gitlink:git-diff[1]. +[[def_pickaxe]]pickaxe:: + The term <> refers to an option to the diffcore + routines that help select changes that add or delete a given text + string. With the --pickaxe-all option, it can be used to view the full + <> that introduced or removed, say, a + particular line of text. See gitlink:git-diff[1]. -plumbing:: - Cute name for core git. +[[def_plumbing]]plumbing:: + Cute name for <>. -porcelain:: - Cute name for programs and program suites depending on core git, - presenting a high level access to core git. Porcelains expose - more of a SCM interface than the plumbing. +[[def_porcelain]]porcelain:: + Cute name for programs and program suites depending on + <>, presenting a high level access to + <>. Porcelains expose more of a <> + interface than the <>. -pull:: - Pulling a branch means to fetch it and merge it. +[[def_pull]]pull:: + Pulling a <> means to <> it and + <> it. -push:: - Pushing a branch means to get the branch's head ref from a remote - repository, find out if it is an ancestor to the branch's local - head ref is a direct, and in that case, putting all objects, which - are reachable from the local head ref, and which are missing from - the remote repository, into the remote object database, and updating - the remote head ref. If the remote head is not an ancestor to the - local head, the push fails. +[[def_push]]push:: + Pushing a <> means to get the <>'s + <> from a remote <>, + find out if it is an ancestor to the <>'s local + <> is a direct, and in that case, putting all + objects, which are <> from the local + <>, and which are missing from the remote + <>, into the remote + <>, and updating the remote + <>. If the remote <> is not an + ancestor to the local <>, the <> fails. -reachable:: - All of the ancestors of a given commit are said to be reachable from - that commit. More generally, one object is reachable from another if - we can reach the one from the other by a chain that follows tags to - whatever they tag, commits to their parents or trees, and trees to the - trees or blobs that they contain. +[[def_reachable]]reachable:: + All of the ancestors of a given <> are said to be + <> from that <>. More + generally, one <> is <> from + another if we can reach the one from the other by a <> + that follows tags to whatever they <>, commits to their + parents or trees, and trees to the trees or blobs that they contain. -rebase:: - To clean a branch by starting from the head of the main line of - development ("master"), and reapply the (possibly cherry-picked) - changes from that branch. +[[def_rebase]]rebase:: + To <> a <> by starting from the + <> of the main line of development + ("<>"), and reapply the (possibly cherry-picked) + changes from that <>. -ref:: - A 40-byte hex representation of a SHA1 or a name that denotes - a particular object. These may be stored in `$GIT_DIR/refs/`. +[[def_ref]]ref:: + A 40-byte hex representation of a <> or a name that + denotes a particular <>. These may be stored in + `$GIT_DIR/refs/`. -refspec:: - A refspec is used by fetch and push to describe the mapping - between remote ref and local ref. They are combined with - a colon in the format :, preceded by an optional - plus sign, +. For example: - `git fetch $URL refs/heads/master:refs/heads/origin` - means "grab the master branch head from the $URL and store - it as my origin branch head". - And `git push $URL refs/heads/master:refs/heads/to-upstream` - means "publish my master branch head as to-upstream branch - at $URL". See also gitlink:git-push[1] +[[def_refspec]]refspec:: + A <> is used by <> and + <> to describe the mapping between remote <> + and local <>. They are combined with a colon in the format + :, preceded by an optional plus sign, +. For example: `git + <> $URL + refs/heads/<>:refs/heads/<>` means + "grab the <> <> <> + from the $URL and store it as my <> + <> <>". And `git <> + $URL refs/heads/<>:refs/heads/to-upstream` means + "publish my <> <> + <> as to-upstream <> at $URL". See + also gitlink:git-push[1] -repository:: - A collection of refs together with an object database containing - all objects, which are reachable from the refs, possibly accompanied - by meta data from one or more porcelains. A repository can - share an object database with other repositories. +[[def_repository]]repository:: + A collection of refs together with an <> containing all objects, which are <> + from the refs, possibly accompanied by meta data from one or more + porcelains. A <> can share an + <> with other repositories. -resolve:: - The action of fixing up manually what a failed automatic merge - left behind. +[[def_resolve]]resolve:: + The action of fixing up manually what a failed automatic + <> left behind. -revision:: - A particular state of files and directories which was stored in - the object database. It is referenced by a commit object. +[[def_revision]]revision:: + A particular state of files and directories which was stored in the + <>. It is referenced by a + <>. -rewind:: - To throw away part of the development, i.e. to assign the head to - an earlier revision. +[[def_rewind]]rewind:: + To throw away part of the development, i.e. to assign the + <> to an earlier <>. -SCM:: +[[def_SCM]]SCM:: Source code management (tool). -SHA1:: - Synonym for object name. +[[def_SHA1]]SHA1:: + Synonym for <>. -shallow repository:: - A shallow repository has an incomplete history some of - whose commits have parents cauterized away (in other - words, git is told to pretend that these commits do not - have the parents, even though they are recorded in the - commit object). This is sometimes useful when you are - interested only in the recent history of a project even - though the real history recorded in the upstream is - much larger. A shallow repository is created by giving - `--depth` option to gitlink:git-clone[1], and its +[[def_shallow_repository]]shallow repository:: + A <> has an incomplete + history some of whose commits have parents cauterized away (in other + words, git is told to pretend that these commits do not have the + parents, even though they are recorded in the <>). This is sometimes useful when you are interested only in the + recent history of a project even though the real history recorded in the + upstream is much larger. A <> + is created by giving `--depth` option to gitlink:git-clone[1], and its history can be later deepened with gitlink:git-fetch[1]. -symref:: - Symbolic reference: instead of containing the SHA1 id itself, it - is of the format 'ref: refs/some/thing' and when referenced, it - recursively dereferences to this reference. 'HEAD' is a prime - example of a symref. Symbolic references are manipulated with - the gitlink:git-symbolic-ref[1] command. +[[def_symref]]symref:: + Symbolic reference: instead of containing the <> id + itself, it is of the format '<>: refs/some/thing' and when + referenced, it recursively dereferences to this reference. 'HEAD' is a + prime example of a <>. Symbolic references are + manipulated with the gitlink:git-symbolic-ref[1] command. -topic branch:: - A regular git branch that is used by a developer to - identify a conceptual line of development. Since branches - are very easy and inexpensive, it is often desirable to - have several small branches that each contain very well - defined concepts or small incremental yet related changes. +[[def_tag]]tag:: + A <> pointing to a <> or + <>. In contrast to a <>, + a <> is not changed by a <>. Tags (not + <> objects) are stored in `$GIT_DIR/refs/tags/`. A git + <> has nothing to do with a Lisp <> (which is + called <> in git's context). A + <> is most typically used to mark a particular point in the + <> ancestry <>. -tracking branch:: - A regular git branch that is used to follow changes from - another repository. A tracking branch should not contain - direct modifications or have local commits made to it. - A tracking branch can usually be identified as the - right-hand-side ref in a Pull: refspec. +[[def_tag_object]]tag object:: + An <> containing a <> pointing to + another <>, which can contain a message just like a + <>. It can also contain a (PGP) + signature, in which case it is called a "signed <>". -tree object:: - An object containing a list of file names and modes along with refs - to the associated blob and/or tree objects. A tree is equivalent - to a directory. +[[def_topic_branch]]topic branch:: + A regular git <> that is used by a developer to + identify a conceptual line of development. Since branches are very easy + and inexpensive, it is often desirable to have several small branches + that each contain very well defined concepts or small incremental yet + related changes. -tree:: - Either a working tree, or a tree object together with the - dependent blob and tree objects (i.e. a stored representation - of a working tree). +[[def_tracking_branch]]tracking branch:: + A regular git <> that is used to follow changes from + another <>. A <> should not contain direct modifications or have local commits + made to it. A <> can usually be + identified as the right-hand-side <> in a Pull: + <>. -tree-ish:: - A ref pointing to either a commit object, a tree object, or a - tag object pointing to a tag or commit or tree object. +[[def_tree]]tree:: + Either a <>, or a <> together with the dependent blob and <> objects + (i.e. a stored representation of a <>). -tag object:: - An object containing a ref pointing to another object, which can - contain a message just like a commit object. It can also - contain a (PGP) signature, in which case it is called a "signed - tag object". +[[def_tree_object]]tree object:: + An <> containing a list of file names and modes along + with refs to the associated blob and/or <> objects. A + <> is equivalent to a <>. -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 - 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. +[[def_tree-ish]]tree-ish:: + A <> pointing to either a <>, a <>, or a <> pointing to a <> or <> or + <>. -unmerged index:: - An index which contains unmerged index entries. +[[def_unmerged_index]]unmerged index:: + An <> which contains <> entries. -unreachable object:: - An object which is not reachable from a branch, tag, or any - other reference. - -working tree:: - The set of files and directories currently being worked on, - i.e. you can work in your working tree without using git at all. +[[def_unreachable_object]]unreachable object:: + An <> which is not <> from a + <>, <>, or any other reference. +[[def_working_tree]]working tree:: + The set of files and directories currently being worked on, i.e. you can + work in your <> without using git at all. diff --git a/Documentation/sort_glossary.pl b/Documentation/sort_glossary.pl deleted file mode 100644 index 4ae6290368..0000000000 --- a/Documentation/sort_glossary.pl +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/perl - -%terms=(); - -while(<>) { - if(/^(\S.*)::$/) { - my $term=$1; - if(defined($terms{$term})) { - die "$1 defined twice\n"; - } - $terms{$term}=""; - LOOP: while(<>) { - if(/^$/) { - last LOOP; - } - if(/^ \S/) { - $terms{$term}.=$_; - } else { - die "Error 1: $_"; - } - } - } -} - -sub format_tab_80 ($) { - my $text=$_[0]; - my $result=""; - $text=~s/\s+/ /g; - $text=~s/^\s+//; - while($text=~/^(.{1,72})(|\s+(\S.*)?)$/) { - $result.=" ".$1."\n"; - $text=$3; - } - return $result; -} - -sub no_spaces ($) { - my $result=$_[0]; - $result=~tr/ /_/; - return $result; -} - -print 'GIT Glossary -============ - -This list is sorted alphabetically: - -'; - -@keys=sort {uc($a) cmp uc($b)} keys %terms; -$pattern='(\b(?>";/eg; - print '[[def_'.no_spaces($key).']]'.$key."::\n" - .format_tab_80($terms{$key})."\n"; -} - -print ' - -Author ------- -Written by Johannes Schindelin and -the git-list . - -GIT ---- -Part of the link:git.html[git] suite -'; - diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 773f65ef83..6df5e617a5 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -3013,9 +3013,6 @@ confusing and scary messages, but it won't actually do anything bad. In contrast, running "git prune" while somebody is actively changing the repository is a *BAD* idea). -Glossary of git terms -===================== - include::glossary.txt[] Notes and todo list for this manual From cbd919221f598811e0eb2587d361581f7552e2e7 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sun, 18 Mar 2007 17:53:29 -0400 Subject: [PATCH 007/130] glossary: clean up cross-references Manual clean-up of cross-references, and also clean up a few definitions (e.g. git-rebase). Signed-off-by: "J. Bruce Fields" --- Documentation/glossary.txt | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/Documentation/glossary.txt b/Documentation/glossary.txt index 82e17db0c0..2465514e46 100644 --- a/Documentation/glossary.txt +++ b/Documentation/glossary.txt @@ -13,7 +13,7 @@ GIT Glossary <> control. That is, all of the `git` administrative and control files that would normally be present in the hidden `.git` sub-directory are directly present in the - `<>.git` <> instead, + `repository.git` directory instead, and no other files are present and checked out. Usually publishers of public repositories make bare repositories available. @@ -23,7 +23,7 @@ GIT Glossary [[def_branch]]branch:: A non-cyclical graph of revisions, i.e. the complete history of a particular <>, which is called the - <> <>. The <> heads + branch <>. The heads are stored in `$GIT_DIR/refs/heads/`. [[def_cache]]cache:: @@ -133,7 +133,7 @@ GIT Glossary together by recording fake ancestry information for commits. This way you can make git pretend the set of parents a <> has is different from what was recorded when the <> was - created. Configured via the `.git/info/<>` file. + created. Configured via the `.git/info/grafts` file. [[def_hash]]hash:: In git's context, synonym to <>. @@ -205,7 +205,7 @@ GIT Glossary [[def_object_type]]object type:: One of the identifiers - "<>","<>","<>" and "blob" + "<>","<>","<>" or "<>" describing the type of an <>. [[def_octopus]]octopus:: @@ -217,7 +217,7 @@ GIT Glossary at least one upstream project which they track. By default '<>' is used for that purpose. New upstream updates will be fetched into remote tracking branches named - <>/name-of-upstream-branch, which you can see using + origin/name-of-upstream-branch, which you can see using "git <> -r". [[def_pack]]pack:: @@ -271,14 +271,15 @@ GIT Glossary <> from that <>. More generally, one <> is <> from another if we can reach the one from the other by a <> - that follows tags to whatever they <>, commits to their - parents or trees, and trees to the trees or blobs that they contain. + that follows <> to whatever they tag, + <> to their parents or trees, and + <> to the trees or <> + that they contain. [[def_rebase]]rebase:: - To <> a <> by starting from the - <> of the main line of development - ("<>"), and reapply the (possibly cherry-picked) - changes from that <>. + To reapply a series of changes from a <> to a + different base, and reset the <> of that branch + to the result. [[def_ref]]ref:: A 40-byte hex representation of a <> or a name that @@ -290,19 +291,18 @@ GIT Glossary <> to describe the mapping between remote <> and local <>. They are combined with a colon in the format :, preceded by an optional plus sign, +. For example: `git - <> $URL - refs/heads/<>:refs/heads/<>` means - "grab the <> <> <> - from the $URL and store it as my <> + fetch $URL refs/heads/master:refs/heads/origin` means + "grab the master <> <> + from the $URL and store it as my origin <> <>". And `git <> - $URL refs/heads/<>:refs/heads/to-upstream` means - "publish my <> <> + $URL refs/heads/master:refs/heads/to-upstream` means + "publish my master <> <> as to-upstream <> at $URL". See also gitlink:git-push[1] [[def_repository]]repository:: A collection of refs together with an <> containing all objects, which are <> + database>> containing all objects which are <> from the refs, possibly accompanied by meta data from one or more porcelains. A <> can share an <> with other repositories. @@ -334,12 +334,12 @@ GIT Glossary object>>). This is sometimes useful when you are interested only in the recent history of a project even though the real history recorded in the upstream is much larger. A <> - is created by giving `--depth` option to gitlink:git-clone[1], and its - history can be later deepened with gitlink:git-fetch[1]. + is created by giving the `--depth` option to gitlink:git-clone[1], and + its history can be later deepened with gitlink:git-fetch[1]. [[def_symref]]symref:: Symbolic reference: instead of containing the <> id - itself, it is of the format '<>: refs/some/thing' and when + itself, it is of the format 'ref: refs/some/thing' and when referenced, it recursively dereferences to this reference. 'HEAD' is a prime example of a <>. Symbolic references are manipulated with the gitlink:git-symbolic-ref[1] command. @@ -347,11 +347,11 @@ GIT Glossary [[def_tag]]tag:: A <> pointing to a <> or <>. In contrast to a <>, - a <> is not changed by a <>. Tags (not - <> objects) are stored in `$GIT_DIR/refs/tags/`. A git - <> has nothing to do with a Lisp <> (which is - called <> in git's context). A - <> is most typically used to mark a particular point in the + a tag is not changed by a <>. Tags (not + <>) are stored in `$GIT_DIR/refs/tags/`. A + git tag has nothing to do with a Lisp tag (which would be + called an <> in git's context). A + tag is most typically used to mark a particular point in the <> ancestry <>. [[def_tag_object]]tag object:: @@ -383,7 +383,7 @@ GIT Glossary [[def_tree_object]]tree object:: An <> containing a list of file names and modes along - with refs to the associated blob and/or <> objects. A + with refs to the associated blob and/or tree objects. A <> is equivalent to a <>. [[def_tree-ish]]tree-ish:: @@ -393,8 +393,8 @@ GIT Glossary <>. [[def_unmerged_index]]unmerged index:: - An <> which contains <> entries. + An <> which contains unmerged + <>. [[def_unreachable_object]]unreachable object:: An <> which is not <> from a From 81b6c950dede5bca60dac0834de25b6f30ec10bb Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Sun, 18 Mar 2007 23:02:14 -0400 Subject: [PATCH 008/130] user-manual: introduce "branch" and "branch head" differently I was using "branch" to mean "head", but that's perhaps a little sloppy; so instead start by using the terms "branch head" and "head", while still quickly falling back on "branch", since that's what people actually say more frequently. Also include glossary references on the first uses of "head" and "tag". Signed-off-by: "J. Bruce Fields" --- Documentation/user-manual.txt | 43 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 6df5e617a5..3ed9f84524 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -288,21 +288,22 @@ collection of files. It stores the history as a compressed collection of interrelated snapshots (versions) of the project's contents. -A single git repository may contain multiple branches. Each branch -is a bookmark referencing a particular point in the project history. -The gitlink:git-branch[1] command shows you the list of branches: +A single git repository may contain multiple branches. It keeps track +of them by keeping a list of <> which reference the +latest version on each branch; the gitlink:git-branch[1] command shows +you the list of branch heads: ------------------------------------------------ $ git branch * master ------------------------------------------------ -A freshly cloned repository contains a single branch, named "master", -and the working directory contains the version of the project -referred to by the master branch. +A freshly cloned repository contains a single branch head, named +"master", and working directory is initialized to the state of +the project referred to by "master". -Most projects also use tags. Tags, like branches, are references -into the project's history, and can be listed using the +Most projects also use <>. Tags, like heads, are +references into the project's history, and can be listed using the gitlink:git-tag[1] command: ------------------------------------------------ @@ -320,9 +321,9 @@ v2.6.13 ------------------------------------------------ Tags are expected to always point at the same version of a project, -while branches are expected to advance as development progresses. +while heads are expected to advance as development progresses. -Create a new branch pointing to one of these versions and check it +Create a new branch head pointing to one of these versions and check it out using gitlink:git-checkout[1]: ------------------------------------------------ @@ -346,10 +347,10 @@ the current branch to point at v2.6.17 instead, with $ git reset --hard v2.6.17 ------------------------------------------------ -Note that if the current branch was your only reference to a +Note that if the current branch head was your only reference to a particular point in history, then resetting that branch may leave you -with no way to find the history it used to point to; so use this -command carefully. +with no way to find the history it used to point to; so use this command +carefully. Understanding History: Commits ------------------------------ @@ -452,17 +453,15 @@ be replaced with another letter or number. Understanding history: What is a branch? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Though we've been using the word "branch" to mean a kind of reference -to a particular commit, the word branch is also commonly used to -refer to the line of commits leading up to that point. In the -example above, git may think of the branch named "A" as just a -pointer to one particular commit, but we may refer informally to the -line of three commits leading up to that point as all being part of +When we need to be precise, we will use the word "branch" to mean a line +of development, and "branch head" (or just "head") to mean a reference +to the most recent commit on a branch. In the example above, the branch +head named "A" is a pointer to one particular commit, but we refer to +the line of three commits leading up to that point as all being part of "branch A". -If we need to make it clear that we're just talking about the most -recent commit on the branch, we may refer to that commit as the -"head" of the branch. +However, when no confusion will result, we often just use the term +"branch" both for branches and for branch heads. Manipulating branches --------------------- From 3358004a006714477c2c44577507081cb5124fa4 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 19 Mar 2007 16:28:51 -0400 Subject: [PATCH 009/130] clean up the delta base cache size a bit Currently there are 3 different ways to deal with the cache size. Let's stick to only one. The compiler is smart enough to produce the exact same code in those cases anyway. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- sha1_file.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index b0b21776e7..8a19d7ee29 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1369,7 +1369,7 @@ static unsigned long pack_entry_hash(struct packed_git *p, off_t base_offset) hash = (unsigned long)p + (unsigned long)base_offset; hash += (hash >> 8) + (hash >> 16); - return hash & 0xff; + return hash % MAX_DELTA_CACHE; } static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset, @@ -1417,13 +1417,13 @@ static void add_delta_base_cache(struct packed_git *p, off_t base_offset, release_delta_base_cache(ent); delta_base_cached += base_size; for (i = 0; delta_base_cached > delta_base_cache_limit - && i < ARRAY_SIZE(delta_base_cache); i++) { + && i < MAX_DELTA_CACHE ; i++) { struct delta_base_cache_entry *f = delta_base_cache + i; if (f->type == OBJ_BLOB) release_delta_base_cache(f); } for (i = 0; delta_base_cached > delta_base_cache_limit - && i < ARRAY_SIZE(delta_base_cache); i++) + && i < MAX_DELTA_CACHE ; i++) release_delta_base_cache(delta_base_cache + i); ent->p = p; From 5e08ecbff219dc68a13eb372b39030134e737c8a Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 19 Mar 2007 16:31:04 -0400 Subject: [PATCH 010/130] use a LRU eviction policy for the delta base cache This provides a smoother degradation in performance when the cache gets trashed due to the delta_base_cache_limit being reached. Limited testing with really small delta_base_cache_limit values appears to confirm this. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- sha1_file.c | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index 8a19d7ee29..9fe2bd69a1 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1355,11 +1355,18 @@ static void *unpack_compressed_entry(struct packed_git *p, #define MAX_DELTA_CACHE (256) static size_t delta_base_cached; + +static struct delta_base_cache_lru_list { + struct delta_base_cache_lru_list *prev; + struct delta_base_cache_lru_list *next; +} delta_base_cache_lru = { &delta_base_cache_lru, &delta_base_cache_lru }; + static struct delta_base_cache_entry { + struct delta_base_cache_lru_list lru; + void *data; struct packed_git *p; off_t base_offset; unsigned long size; - void *data; enum object_type type; } delta_base_cache[MAX_DELTA_CACHE]; @@ -1387,6 +1394,8 @@ static void *cache_or_unpack_entry(struct packed_git *p, off_t base_offset, found_cache_entry: if (!keep_cache) { ent->data = NULL; + ent->lru.next->prev = ent->lru.prev; + ent->lru.prev->next = ent->lru.next; delta_base_cached -= ent->size; } else { @@ -1404,6 +1413,8 @@ static inline void release_delta_base_cache(struct delta_base_cache_entry *ent) if (ent->data) { free(ent->data); ent->data = NULL; + ent->lru.next->prev = ent->lru.prev; + ent->lru.prev->next = ent->lru.next; delta_base_cached -= ent->size; } } @@ -1411,26 +1422,38 @@ static inline void release_delta_base_cache(struct delta_base_cache_entry *ent) static void add_delta_base_cache(struct packed_git *p, off_t base_offset, void *base, unsigned long base_size, enum object_type type) { - unsigned long i, hash = pack_entry_hash(p, base_offset); + unsigned long hash = pack_entry_hash(p, base_offset); struct delta_base_cache_entry *ent = delta_base_cache + hash; + struct delta_base_cache_lru_list *lru; release_delta_base_cache(ent); delta_base_cached += base_size; - for (i = 0; delta_base_cached > delta_base_cache_limit - && i < MAX_DELTA_CACHE ; i++) { - struct delta_base_cache_entry *f = delta_base_cache + i; + + for (lru = delta_base_cache_lru.next; + delta_base_cached > delta_base_cache_limit + && lru != &delta_base_cache_lru; + lru = lru->next) { + struct delta_base_cache_entry *f = (void *)lru; if (f->type == OBJ_BLOB) release_delta_base_cache(f); } - for (i = 0; delta_base_cached > delta_base_cache_limit - && i < MAX_DELTA_CACHE ; i++) - release_delta_base_cache(delta_base_cache + i); + for (lru = delta_base_cache_lru.next; + delta_base_cached > delta_base_cache_limit + && lru != &delta_base_cache_lru; + lru = lru->next) { + struct delta_base_cache_entry *f = (void *)lru; + release_delta_base_cache(f); + } ent->p = p; ent->base_offset = base_offset; ent->type = type; ent->data = base; ent->size = base_size; + ent->lru.next = &delta_base_cache_lru; + ent->lru.prev = delta_base_cache_lru.prev; + delta_base_cache_lru.prev->next = &ent->lru; + delta_base_cache_lru.prev = &ent->lru; } static void *unpack_delta_entry(struct packed_git *p, From 567fb65e251d946cee2b73a9b188231652fe663c Mon Sep 17 00:00:00 2001 From: James Bowes Date: Mon, 19 Mar 2007 17:42:40 -0400 Subject: [PATCH 011/130] Replace remaining instances of strdup with xstrdup. Signed-off-by: James Bowes Signed-off-by: Junio C Hamano --- builtin-log.c | 2 +- commit.c | 2 +- revision.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/builtin-log.c b/builtin-log.c index 865832c85e..71df957eaa 100644 --- a/builtin-log.c +++ b/builtin-log.c @@ -35,7 +35,7 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix, if (!prefixcmp(arg, "--encoding=")) { arg += 11; if (strcmp(arg, "none")) - git_log_output_encoding = strdup(arg); + git_log_output_encoding = xstrdup(arg); else git_log_output_encoding = ""; } diff --git a/commit.c b/commit.c index 5b9234e12e..718e568855 100644 --- a/commit.c +++ b/commit.c @@ -706,7 +706,7 @@ static char *logmsg_reencode(const struct commit *commit, encoding = get_header(commit, "encoding"); use_encoding = encoding ? encoding : utf8; if (!strcmp(use_encoding, output_encoding)) - out = strdup(commit->buffer); + out = xstrdup(commit->buffer); else out = reencode_string(commit->buffer, output_encoding, use_encoding); diff --git a/revision.c b/revision.c index bcdb6a1212..c680dcb8ba 100644 --- a/revision.c +++ b/revision.c @@ -1038,7 +1038,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch if (!prefixcmp(arg, "--encoding=")) { arg += 11; if (strcmp(arg, "none")) - git_log_output_encoding = strdup(arg); + git_log_output_encoding = xstrdup(arg); else git_log_output_encoding = ""; continue; From 57584d9eddc3482c5db0308203b9df50dc62109c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 19 Mar 2007 22:17:10 -0700 Subject: [PATCH 012/130] blame: micro-optimize cmp_suspect() The commit structures are guaranteed their uniqueness by the object layer, so we can check their address and see if they are the same without going down to the object sha1 level. Signed-off-by: Junio C Hamano --- builtin-blame.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index b51cdc71fa..104521e673 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -182,9 +182,8 @@ struct scoreboard { static int cmp_suspect(struct origin *a, struct origin *b) { - int cmp = hashcmp(a->commit->object.sha1, b->commit->object.sha1); - if (cmp) - return cmp; + if (a->commit != b->commit) + return 1; return strcmp(a->path, b->path); } From 824f782c3f8f2db8e884b0c555d21ed4cfd6fff2 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 20 Mar 2007 04:05:10 +0100 Subject: [PATCH 013/130] xdiff/xutils.c(xdl_hash_record): factor out whitespace handling Since in at least one use case, xdl_hash_record() takes over 15% of the CPU time, it makes sense to even micro-optimize it. For many cases, no whitespace special handling is needed, and in these cases we should not even bother to check for whitespace in _every_ iteration of the loop. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- xdiff/xutils.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/xdiff/xutils.c b/xdiff/xutils.c index 3653864e4b..bf91c0f73c 100644 --- a/xdiff/xutils.c +++ b/xdiff/xutils.c @@ -236,12 +236,13 @@ int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags) return 0; } -unsigned long xdl_hash_record(char const **data, char const *top, long flags) { +static unsigned long xdl_hash_record_with_whitespace(char const **data, + char const *top, long flags) { unsigned long ha = 5381; char const *ptr = *data; for (; ptr < top && *ptr != '\n'; ptr++) { - if (isspace(*ptr) && (flags & XDF_WHITESPACE_FLAGS)) { + if (isspace(*ptr)) { const char *ptr2 = ptr; while (ptr + 1 < top && isspace(ptr[1]) && ptr[1] != '\n') @@ -270,6 +271,23 @@ unsigned long xdl_hash_record(char const **data, char const *top, long flags) { } +unsigned long xdl_hash_record(char const **data, char const *top, long flags) { + unsigned long ha = 5381; + char const *ptr = *data; + + if (flags & XDF_WHITESPACE_FLAGS) + return xdl_hash_record_with_whitespace(data, top, flags); + + for (; ptr < top && *ptr != '\n'; ptr++) { + ha += (ha << 5); + ha ^= (unsigned long) *ptr; + } + *data = ptr < top ? ptr + 1: ptr; + + return ha; +} + + unsigned int xdl_hashbits(unsigned int size) { unsigned int val = 1, bits = 0; From e29b96d5aa942325ddba0488c819ef5dd8fd7c48 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 20 Mar 2007 03:29:56 +0100 Subject: [PATCH 014/130] Add a HOWTO for setting up a standalone git daemon Setting up a git-daemon came up the other day on IRC, and it is slightly non trivial for the uninitiated. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/howto/use-git-daemon.txt | 52 ++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/howto/use-git-daemon.txt diff --git a/Documentation/howto/use-git-daemon.txt b/Documentation/howto/use-git-daemon.txt new file mode 100644 index 0000000000..1a1eb246bf --- /dev/null +++ b/Documentation/howto/use-git-daemon.txt @@ -0,0 +1,52 @@ +How to use git-daemon + +Git can be run in inetd mode and in stand alone mode. But all you want is +let a coworker pull from you, and therefore need to set up a git server +real quick, right? + +Note that git-daemon is not really chatty at the moment, especially when +things do not go according to plan (e.g. a socket could not be bound). + +Another word of warning: if you run + + $ git ls-remote git://127.0.0.1/rule-the-world.git + +and you see a message like + + fatal: The remote end hung up unexpectedly + +it only means that _something_ went wrong. To find out _what_ went wrong, +you have to ask the server. (Git refuses to be more precise for your +security only. Take off your shoes now. You have any coins in your pockets? +Sorry, not allowed -- who knows what you planned to do with them?) + +With these two caveats, let's see an example: + + $ git daemon --reuseaddr --verbose --base-path=/home/gitte/git \ + --export-all -- /home/gitte/git/rule-the-world.git + +(Of course, unless your user name is `gitte` _and_ your repository is in +~/rule-the-world.git, you have to adjust the paths. If your repository is +not bare, be aware that you have to type the path to the .git directory!) + +This invocation tries to reuse the address if it is already taken +(this can save you some debugging, because otherwise killing and restarting +git-daemon could just silently fail to bind to a socket). + +Also, it is (relatively) verbose when somebody actually connects to it. +It also sets the base path, which means that all the projects which can be +accessed using this daemon have to reside in or under that path. + +The option `--export-all` just means that you _don't_ have to create a +file named `git-daemon-export-ok` in each exported repository. (Otherwise, +git-daemon would complain loudly, and refuse to cooperate.) + +Last of all, the repository which should be exported is specified. It is +a good practice to put the paths after a "--" separator. + +Now, test your daemon with + + $ git ls-remote git://127.0.0.1/rule-the-world.git + +If this does not work, find out why, and submit a patch to this document. + From 1b89ef1731d21c607b06cc48be375b7de882acf7 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 20 Mar 2007 03:41:11 +0100 Subject: [PATCH 015/130] Provide some technical documentation for shallow clones There has not been any work on the shallow stuff lately, so it is hard to find out what it does, and how. This document describes the ideas as well as the current problems, and can serve as a starting point for shallow people. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/technical/shallow.txt | 49 +++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 Documentation/technical/shallow.txt diff --git a/Documentation/technical/shallow.txt b/Documentation/technical/shallow.txt new file mode 100644 index 0000000000..559263af48 --- /dev/null +++ b/Documentation/technical/shallow.txt @@ -0,0 +1,49 @@ +Def.: Shallow commits do have parents, but not in the shallow +repo, and therefore grafts are introduced pretending that +these commits have no parents. + +The basic idea is to write the SHA1s of shallow commits into +$GIT_DIR/shallow, and handle its contents like the contents +of $GIT_DIR/info/grafts (with the difference that shallow +cannot contain parent information). + +This information is stored in a new file instead of grafts, or +even the config, since the user should not touch that file +at all (even throughout development of the shallow clone, it +was never manually edited!). + +Each line contains exactly one SHA1. When read, a commit_graft +will be constructed, which has nr_parent < 0 to make it easier +to discern from user provided grafts. + +Since fsck-objects relies on the library to read the objects, +it honours shallow commits automatically. + +There are some unfinished ends of the whole shallow business: + +- maybe we have to force non-thin packs when fetching into a + shallow repo (ATM they are forced non-thin). + +- A special handling of a shallow upstream is needed. At some + stage, upload-pack has to check if it sends a shallow commit, + and it should send that information early (or fail, if the + client does not support shallow repositories). There is no + support at all for this in this patch series. + +- Instead of locking $GIT_DIR/shallow at the start, just + the timestamp of it is noted, and when it comes to writing it, + a check is performed if the mtime is still the same, dying if + it is not. + +- It is unclear how "push into/from a shallow repo" should behave. + +- If you deepen a history, you'd want to get the tags of the + newly stored (but older!) commits. This does not work right now. + +To make a shallow clone, you can call "git-clone --depth 20 repo". +The result contains only commit chains with a length of at most 20. +It also writes an appropriate $GIT_DIR/shallow. + +You can deepen a shallow repository with "git-fetch --depth 20 +repo branch", which will fetch branch from repo, but stop at depth +20, updating $GIT_DIR/shallow. From 3e993bb657daad31d8a7b1ef0a6a9f73bdd5f950 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 20 Mar 2007 00:33:41 -0400 Subject: [PATCH 016/130] contrib/continuous: a continuous integration build manager This is a simple but powerful continuous integration build system for Git. It works by receiving push events from repositories through the post-receive hook, aggregates them on a per-branch basis into a first-come-first-serve build queue, and lets a background build daemon perform builds one at a time. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- contrib/continuous/cidaemon | 503 +++++++++++++++++++++++ contrib/continuous/post-receive-cinotify | 104 +++++ 2 files changed, 607 insertions(+) create mode 100644 contrib/continuous/cidaemon create mode 100644 contrib/continuous/post-receive-cinotify diff --git a/contrib/continuous/cidaemon b/contrib/continuous/cidaemon new file mode 100644 index 0000000000..4009a151de --- /dev/null +++ b/contrib/continuous/cidaemon @@ -0,0 +1,503 @@ +#!/usr/bin/perl +# +# A daemon that waits for update events sent by its companion +# post-receive-cinotify hook, checks out a new copy of source, +# compiles it, and emails the guilty parties if the compile +# (and optionally test suite) fails. +# +# To use this daemon, configure it and run it. It will disconnect +# from your terminal and fork into the background. The daemon must +# have local filesystem access to the source repositories, as it +# uses objects/info/alternates to avoid copying objects. +# +# Add its companion post-receive-cinotify hook as the post-receive +# hook to each repository that the daemon should monitor. Yes, a +# single daemon can monitor more than one repository. +# +# To use multiple daemons on the same system, give them each a +# unique queue file and tmpdir. +# +# Global Config +# ------------- +# Reads from a Git style configuration file. This will be +# ~/.gitconfig by default but can be overridden by setting +# the GIT_CONFIG_FILE environment variable before starting. +# +# cidaemon.smtpHost +# Hostname of the SMTP server the daemon will send email +# through. Defaults to 'localhost'. +# +# cidaemon.smtpUser +# Username to authenticate to the SMTP server as. This +# variable is optional; if it is not supplied then no +# authentication will be performed. +# +# cidaemon.smtpPassword +# Password to authenticate to the SMTP server as. This +# variable is optional. If not supplied but smtpUser was, +# the daemon prompts for the password before forking into +# the background. +# +# cidaemon.smtpAuth +# Type of authentication to perform with the SMTP server. +# If set to 'login' and smtpUser was defined, this will +# use the AUTH LOGIN command, which is suitable for use +# with at least one version of Microsoft Exchange Server. +# If not set the daemon will use whatever auth methods +# are supported by your version of Net::SMTP. +# +# cidaemon.email +# Email address that daemon generated emails will be sent +# from. This should be a useful email address within your +# organization. Required. +# +# cidaemon.name +# Human friendly name that the daemon will send emails as. +# Defaults to 'cidaemon'. +# +# cidaemon.scanDelay +# Number of seconds to sleep between polls of the queue file. +# Defaults to 60. +# +# cidaemon.recentCache +# Number of recent commit SHA-1s per repository to cache and +# skip building if they appear again. This is useful to avoid +# rebuilding the same commit multiple times just because it was +# pushed into more than one branch. Defaults to 100. +# +# cidaemon.tmpdir +# Scratch directory to create the builds within. The daemon +# makes a new subdirectory for each build, then deletes it when +# the build has finished. The pid file is also placed here. +# Defaults to '/tmp'. +# +# cidaemon.queue +# Path to the queue file that the post-receive-cinotify hook +# appends events to. This file is polled by the daemon. It +# must not be on an NFS mount (uses flock). Required. +# +# cidaemon.nocc +# Perl regex patterns to match against author and committer +# lines. If a pattern matches, that author or committer will +# not be notified of a build failure. +# +# Per Repository Config +# ---------------------- +# Read from the source repository's config file. +# +# builder.command +# Shell command to execute the build. This command must +# return 0 on "success" and non-zero on failure. If you +# also want to run a test suite, make sure your command +# does that too. Required. +# +# builder.queue +# Queue file to notify the cidaemon through. Should match +# cidaemon.queue. If not set the hook will not notify the +# cidaemon. +# +# builder.skip +# Perl regex patterns of refs that should not be sent to +# cidaemon. Updates of these refs will be ignored. +# +# builder.newBranchBase +# Glob patterns of refs that should be used to form the +# 'old' revions of a newly created ref. This should set +# to be globs that match your 'mainline' branches. This +# way a build failure of a brand new topic branch does not +# attempt to email everyone since the beginning of time; +# instead it only emails those authors of commits not in +# these 'mainline' branches. + +local $ENV{PATH} = join ':', qw( + /opt/git/bin + /usr/bin + /bin + ); + +use strict; +use warnings; +use FindBin qw($RealBin); +use File::Spec; +use lib File::Spec->catfile($RealBin, '..', 'perl5'); +use Storable qw(retrieve nstore); +use Fcntl ':flock'; +use POSIX qw(strftime); +use Getopt::Long qw(:config no_auto_abbrev auto_help); + +sub git_config ($;$) +{ + my $var = shift; + my $required = shift || 0; + local *GIT; + open GIT, '-|','git','config','--get',$var; + my $r = ; + chop $r if $r; + close GIT; + die "error: $var not set.\n" if ($required && !$r); + return $r; +} + +package EXCHANGE_NET_SMTP; + +# Microsoft Exchange Server requires an 'AUTH LOGIN' +# style of authentication. This is different from +# the default supported by Net::SMTP so we subclass +# and override the auth method to support that. + +use Net::SMTP; +use Net::Cmd; +use MIME::Base64 qw(encode_base64); +our @ISA = qw(Net::SMTP); +our $auth_type = ::git_config 'cidaemon.smtpAuth'; + +sub new +{ + my $self = shift; + my $type = ref($self) || $self; + $type->SUPER::new(@_); +} + +sub auth +{ + my $self = shift; + return $self->SUPER::auth(@_) unless $auth_type eq 'login'; + + my $user = encode_base64 shift, ''; + my $pass = encode_base64 shift, ''; + return 0 unless CMD_MORE == $self->command("AUTH LOGIN")->response; + return 0 unless CMD_MORE == $self->command($user)->response; + CMD_OK == $self->command($pass)->response; +} + +package main; + +my ($debug_flag, %recent); + +my $ex_host = git_config('cidaemon.smtpHost') || 'localhost'; +my $ex_user = git_config('cidaemon.smtpUser'); +my $ex_pass = git_config('cidaemon.smtpPassword'); + +my $ex_from_addr = git_config('cidaemon.email', 1); +my $ex_from_name = git_config('cidaemon.name') || 'cidaemon'; + +my $scan_delay = git_config('cidaemon.scanDelay') || 60; +my $recent_size = git_config('cidaemon.recentCache') || 100; +my $tmpdir = git_config('cidaemon.tmpdir') || '/tmp'; +my $queue_name = git_config('cidaemon.queue', 1); +my $queue_lock = "$queue_name.lock"; + +my @nocc_list; +open GIT,'git config --get-all cidaemon.nocc|'; +while () { + chop; + push @nocc_list, $_; +} +close GIT; + +sub nocc_author ($) +{ + local $_ = shift; + foreach my $pat (@nocc_list) { + return 1 if /$pat/; + } + 0; +} + +sub input_echo ($) +{ + my $prompt = shift; + + local $| = 1; + print $prompt; + my $input = ; + chop $input; + return $input; +} + +sub input_noecho ($) +{ + my $prompt = shift; + + my $end = sub {system('stty','echo');print "\n";exit}; + local $SIG{TERM} = $end; + local $SIG{INT} = $end; + system('stty','-echo'); + + local $| = 1; + print $prompt; + my $input = ; + system('stty','echo'); + print "\n"; + chop $input; + return $input; +} + +sub rfc2822_date () +{ + strftime("%a, %d %b %Y %H:%M:%S %Z", localtime); +} + +sub send_email ($$$) +{ + my ($subj, $body, $to) = @_; + my $now = rfc2822_date; + my $to_str = ''; + my @rcpt_to; + foreach (@$to) { + my $s = $_; + $s =~ s/^/"/; + $s =~ s/(\s+<)/"$1/; + $to_str .= ', ' if $to_str; + $to_str .= $s; + push @rcpt_to, $1 if $s =~ /<(.*)>/; + } + die "Nobody to send to.\n" unless @rcpt_to; + my $msg = < +To: $to_str +Date: $now +Subject: $subj + +$body +EOF + + my $smtp = EXCHANGE_NET_SMTP->new(Host => $ex_host) + or die "Cannot connect to $ex_host: $!\n"; + if ($ex_user && $ex_pass) { + $smtp->auth($ex_user,$ex_pass) + or die "$ex_host rejected $ex_user\n"; + } + $smtp->mail($ex_from_addr) + or die "$ex_host rejected $ex_from_addr\n"; + scalar($smtp->recipient(@rcpt_to, { SkipBad => 1 })) + or die "$ex_host did not accept any addresses.\n"; + $smtp->data($msg) + or die "$ex_host rejected message data\n"; + $smtp->quit; +} + +sub pop_queue () +{ + open LOCK, ">$queue_lock" or die "Can't open $queue_lock: $!"; + flock LOCK, LOCK_EX; + + my $queue = -f $queue_name ? retrieve $queue_name : []; + my $ent = shift @$queue; + nstore $queue, $queue_name; + + flock LOCK, LOCK_UN; + close LOCK; + $ent; +} + +sub git_exec (@) +{ + system('git',@_) == 0 or die "Cannot git " . join(' ', @_) . "\n"; +} + +sub git_val (@) +{ + open(C, '-|','git',@_); + my $r = ; + chop $r if $r; + close C; + $r; +} + +sub do_build ($$) +{ + my ($git_dir, $new) = @_; + + my $tmp = File::Spec->catfile($tmpdir, "builder$$"); + system('rm','-rf',$tmp) == 0 or die "Cannot clear $tmp\n"; + die "Cannot clear $tmp.\n" if -e $tmp; + + my $result = 1; + eval { + my $command; + { + local $ENV{GIT_DIR} = $git_dir; + $command = git_val 'config','builder.command'; + } + die "No builder.command for $git_dir.\n" unless $command; + + git_exec 'clone','-n','-l','-s',$git_dir,$tmp; + chmod 0700, $tmp or die "Cannot lock $tmp\n"; + chdir $tmp or die "Cannot enter $tmp\n"; + + git_exec 'update-ref','HEAD',$new; + git_exec 'read-tree','-m','-u','HEAD','HEAD'; + system $command; + if ($? == -1) { + print STDERR "failed to execute '$command': $!\n"; + $result = 1; + } elsif ($? & 127) { + my $sig = $? & 127; + print STDERR "'$command' died from signal $sig\n"; + $result = 1; + } else { + my $r = $? >> 8; + print STDERR "'$command' exited with $r\n" if $r; + $result = $r; + } + }; + if ($@) { + $result = 2; + print STDERR "$@\n"; + } + + chdir '/'; + system('rm','-rf',$tmp); + rmdir $tmp; + $result; +} + +sub build_failed ($$$$$) +{ + my ($git_dir, $ref, $old, $new, $msg) = @_; + + $git_dir =~ m,/([^/]+)$,; + my $repo_name = $1; + $ref =~ s,^refs/(heads|tags)/,,; + + my %authors; + my $shortlog; + my $revstr; + { + local $ENV{GIT_DIR} = $git_dir; + my @revs = ($new); + push @revs, '--not', @$old if @$old; + open LOG,'-|','git','rev-list','--pretty=raw',@revs; + while () { + if (s/^(author|committer) //) { + chomp; + s/>.*$/>/; + $authors{$_} = 1 unless nocc_author $_; + } + } + close LOG; + open LOG,'-|','git','shortlog',@revs; + $shortlog .= $_ while ; + close LOG; + $revstr = join(' ', @revs); + } + + my @to = sort keys %authors; + unless (@to) { + print STDERR "error: No authors in $revstr\n"; + return; + } + + my $subject = "[$repo_name] $ref : Build Failed"; + my $body = <&W'); + open(STDERR, '>&W'); + exit do_build $git_dir, $new; + } else { + close W; + my $out = ''; + $out .= $_ while ; + close R; + waitpid $builder, 0; + build_failed $git_dir, $ref, $old, $new, $out if $?; + } + + print "DONE\n\n" if $debug_flag; +} + +sub daemon_loop () +{ + my $run = 1; + my $stop_sub = sub {$run = 0}; + $SIG{HUP} = $stop_sub; + $SIG{INT} = $stop_sub; + $SIG{TERM} = $stop_sub; + + mkdir $tmpdir, 0755; + my $pidfile = File::Spec->catfile($tmpdir, "cidaemon.pid"); + open(O, ">$pidfile"); print O "$$\n"; close O; + + while ($run) { + my $ent = pop_queue; + if ($ent) { + my ($git_dir, $ref, $old, $new) = @$ent; + + $ent = $recent{$git_dir}; + $recent{$git_dir} = $ent = [[], {}] unless $ent; + my ($rec_arr, $rec_hash) = @$ent; + next if $rec_hash->{$new}++; + while (@$rec_arr >= $recent_size) { + my $to_kill = shift @$rec_arr; + delete $rec_hash->{$to_kill}; + } + push @$rec_arr, $new; + + run_build $git_dir, $ref, $old, $new; + } else { + sleep $scan_delay; + } + } + + unlink $pidfile; +} + +$debug_flag = 0; +GetOptions( + 'debug|d' => \$debug_flag, + 'smtp-user=s' => \$ex_user, +) or die "usage: $0 [--debug] [--smtp-user=user]\n"; + +$ex_pass = input_noecho("$ex_user SMTP password: ") + if ($ex_user && !$ex_pass); + +if ($debug_flag) { + daemon_loop; + exit 0; +} + +my $daemon = fork(); +if (!defined $daemon) { + die "cannot fork daemon: $!"; +} elsif (0 == $daemon) { + close STDIN;open(STDIN, '/dev/null'); + close STDOUT;open(STDOUT, '>/dev/null'); + close STDERR;open(STDERR, '>/dev/null'); + daemon_loop; + exit 0; +} else { + print "Daemon $daemon running in the background.\n"; +} diff --git a/contrib/continuous/post-receive-cinotify b/contrib/continuous/post-receive-cinotify new file mode 100644 index 0000000000..b8f5a609af --- /dev/null +++ b/contrib/continuous/post-receive-cinotify @@ -0,0 +1,104 @@ +#!/usr/bin/perl +# +# A hook that notifies its companion cidaemon through a simple +# queue file that a ref has been updated via a push (actually +# by a receive-pack running on the server). +# +# See cidaemon for per-repository configuration details. +# +# To use this hook, add it as the post-receive hook, make it +# executable, and set its configuration options. +# + +local $ENV{PATH} = '/opt/git/bin'; + +use strict; +use warnings; +use File::Spec; +use Storable qw(retrieve nstore); +use Fcntl ':flock'; + +my $git_dir = File::Spec->rel2abs($ENV{GIT_DIR}); +my $queue_name = `git config --get builder.queue`;chop $queue_name; +$queue_name =~ m,^([^\s]+)$,; $queue_name = $1; # untaint +unless ($queue_name) { + 1 while ; + print STDERR "\nerror: builder.queue not set. Not enqueing.\n\n"; + exit; +} +my $queue_lock = "$queue_name.lock"; + +my @skip; +open S, "git config --get-all builder.skip|"; +while () { + chop; + push @skip, $_; +} +close S; + +my @new_branch_base; +open S, "git config --get-all builder.newBranchBase|"; +while () { + chop; + push @new_branch_base, $_; +} +close S; + +sub skip ($) +{ + local $_ = shift; + foreach my $p (@skip) { + return 1 if /^$p/; + } + 0; +} + +open LOCK, ">$queue_lock" or die "Can't open $queue_lock: $!"; +flock LOCK, LOCK_EX; + +my $queue = -f $queue_name ? retrieve $queue_name : []; +my %existing; +foreach my $r (@$queue) { + my ($gd, $ref) = @$r; + $existing{$gd}{$ref} = $r; +} + +my @new_branch_commits; +my $loaded_new_branch_commits = 0; + +while () { + chop; + my ($old, $new, $ref) = split / /, $_, 3; + + next if $old eq $new; + next if $new =~ /^0{40}$/; + next if skip $ref; + + my $r = $existing{$git_dir}{$ref}; + if ($r) { + $r->[3] = $new; + } else { + if ($old =~ /^0{40}$/) { + if (!$loaded_new_branch_commits && @new_branch_base) { + open M,'-|','git','show-ref',@new_branch_base; + while () { + ($_) = split / /, $_; + push @new_branch_commits, $_; + } + close M; + $loaded_new_branch_commits = 1; + } + $old = [@new_branch_commits]; + } else { + $old = [$old]; + } + + $r = [$git_dir, $ref, $old, $new]; + $existing{$git_dir}{$ref} = $r; + push @$queue, $r; + } +} +nstore $queue, $queue_name; + +flock LOCK, LOCK_UN; +close LOCK; From 456cdf6edbf0c14b75fd9048708e9abea43e6aa1 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Mon, 19 Mar 2007 22:49:53 -0700 Subject: [PATCH 017/130] Fix loose object uncompression check. The thing is, if the output buffer is empty, we should *still* actually use the zlib routines to *unpack* that empty output buffer. But we had a test that said "only unpack if we still expect more output". So we wouldn't use up all the zlib stream, because we felt that we didn't need it, because we already had all the bytes we wanted. And it was "true": we did have all the output data. We just needed to also eat all the input data! We've had this bug before - thinking that we don't need to inflate() anything because we already had it all.. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- sha1_file.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index 9fe2bd69a1..c445a24718 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1030,14 +1030,27 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size n = size; memcpy(buf, (char *) buffer + bytes, n); bytes = n; - if (bytes < size) { + if (bytes <= size) { + /* + * The above condition must be (bytes <= size), not + * (bytes < size). In other words, even though we + * expect no more output and set avail_out to zer0, + * the input zlib stream may have bytes that express + * "this concludes the stream", and we *do* want to + * eat that input. + * + * Otherwise we would not be able to test that we + * consumed all the input to reach the expected size; + * we also want to check that zlib tells us that all + * went well with status == Z_STREAM_END at the end. + */ stream->next_out = buf + bytes; stream->avail_out = size - bytes; while (status == Z_OK) status = inflate(stream, Z_FINISH); } buf[size] = 0; - if ((status == Z_OK || status == Z_STREAM_END) && !stream->avail_in) { + if (status == Z_STREAM_END && !stream->avail_in) { inflateEnd(stream); return buf; } From 7e8c8255e9bf33dd046b95c4bd1ef554ad3c71b2 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Mon, 19 Mar 2007 19:18:18 -0700 Subject: [PATCH 018/130] make git clone -q suppress the noise with http fetch We already have -q in git clone. So for those who care to suppress the noise during an http based clone, make -q actually do a quiet http fetch. Signed-off-by: Chris Wright Cc: Fernando Herrera Signed-off-by: Junio C Hamano --- git-clone.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/git-clone.sh b/git-clone.sh index de51983584..6ba477d1f4 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -42,6 +42,7 @@ clone_dumb_http () { http_fetch "$1/info/refs" "$clone_tmp/refs" || die "Cannot get remote repository information. Perhaps git-update-server-info needs to be run there?" + test "z$quiet" = z && v=-v || v= while read sha1 refname do name=`expr "z$refname" : 'zrefs/\(.*\)'` && @@ -59,7 +60,7 @@ Perhaps git-update-server-info needs to be run there?" else tname=$name fi - git-http-fetch -v -a -w "$tname" "$name" "$1/" || exit 1 + git-http-fetch $v -a -w "$tname" "$name" "$1/" || exit 1 done <"$clone_tmp/refs" rm -fr "$clone_tmp" http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" || From 08727ea8bba8c81678e5cf15124ada23ad097bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Santi=20B=C3=A9jar?= Date: Mon, 19 Mar 2007 00:16:23 +0100 Subject: [PATCH 019/130] git-fetch: Fix single_force in append_fetch_head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the single force (+) when fetched with fetch_per_ref. Also use $LF as separator because IFS is $LF. Signed-off-by: Santi Béjar Signed-off-by: Junio C Hamano --- git-fetch.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-fetch.sh b/git-fetch.sh index e218042843..93349330d4 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -110,8 +110,8 @@ ls_remote_result=$(git ls-remote $exec "$remote") || append_fetch_head () { flags= - test -n "$verbose" && flags="$flags -v" - test -n "$force" && flags="$flags -f" + test -n "$verbose" && flags="$flags$LF-v" + test -n "$force$single_force" && flags="$flags$LF-f" GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \ git-fetch--tool $flags append-fetch-head "$@" } From 8bf0e3d15d3d327ae16d8eaa56374492d03a7b88 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Sun, 18 Mar 2007 21:34:46 +0100 Subject: [PATCH 020/130] Teach git-remote to list pushed branches. The configured refspecs are printed almost verbatim, i.e. both the local and the remote branch name separated by a colon are printed; only the prefix 'refs/heads/' is removed, like this: Local branch(es) pushed with 'git push' master refs/tags/*:refs/tags/* next:next Signed-off-by: Johannes Sixt Signed-off-by: Junio C Hamano --- git-remote.perl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/git-remote.perl b/git-remote.perl index bd70bf1ddd..52013fe76d 100755 --- a/git-remote.perl +++ b/git-remote.perl @@ -15,6 +15,10 @@ sub add_remote_config { $hash->{$name}{'FETCH'} ||= []; push @{$hash->{$name}{'FETCH'}}, $value; } + elsif ($what eq 'push') { + $hash->{$name}{'PUSH'} ||= []; + push @{$hash->{$name}{'PUSH'}}, $value; + } if (!exists $hash->{$name}{'SOURCE'}) { $hash->{$name}{'SOURCE'} = 'config'; } @@ -44,7 +48,8 @@ sub add_remote_remotes { } } elsif (/^Push:\s*(.*)$/) { - ; # later + $it->{'PUSH'} ||= []; + push @{$it->{'PUSH'}}, $1; } elsif (/^Pull:\s*(.*)$/) { $it->{'FETCH'} ||= []; @@ -250,6 +255,15 @@ sub show_remote { if ($info->{'LS_REMOTE'}) { show_mapping($name, $info); } + if ($info->{'PUSH'}) { + my @pushed = map { + s|^refs/heads/||; + s|:refs/heads/|:|; + $_; + } @{$info->{'PUSH'}}; + print " Local branch(es) pushed with 'git push'\n"; + print " @pushed\n"; + } } sub add_remote { From 8685da42561d16bb01aeaa1a2392459965187925 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 20 Mar 2007 15:32:35 -0400 Subject: [PATCH 021/130] don't ever allow SHA1 collisions to exist by fetching a pack Waaaaaaay back Git was considered to be secure as it never overwrote an object it already had. This was ensured by always unpacking the packfile received over the network (both in fetch and receive-pack) and our already existing logic to not create a loose object for an object we already have. Lately however we keep "large-ish" packfiles on both fetch and push by running them through index-pack instead of unpack-objects. This would let an attacker perform a birthday attack. How? Assume the attacker knows a SHA-1 that has two different data streams. He knows the client is likely to have the "good" one. So he sends the "evil" variant to the other end as part of a "large-ish" packfile. The recipient keeps that packfile, and indexes it. Now since this is a birthday attack there is a SHA-1 collision; two objects exist in the repository with the same SHA-1. They have *very* different data streams. One of them is "evil". Currently the poor recipient cannot tell the two objects apart, short of by examining the timestamp of the packfiles. But lets say the recipient repacks before he realizes he's been attacked. We may wind up packing the "evil" version of the object, and deleting the "good" one. This is made *even more likely* by Junio's recent rearrange_packed_git patch (b867092f). It is extremely unlikely for a SHA1 collisions to occur, but if it ever happens with a remote (hence untrusted) object we simply must not let the fetch succeed. Normally received packs should not contain objects we already have. But when they do we must ensure duplicated objects with the same SHA1 actually contain the same data. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- index-pack.c | 21 +++++++++++++++++---- t/t5300-pack-object.sh | 10 ++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/index-pack.c b/index-pack.c index b405864be9..4effb2da6d 100644 --- a/index-pack.c +++ b/index-pack.c @@ -345,7 +345,8 @@ static int find_delta_children(const union delta_base *base, } static void sha1_object(const void *data, unsigned long size, - enum object_type type, unsigned char *sha1) + enum object_type type, unsigned char *sha1, + int test_for_collision) { SHA_CTX ctx; char header[50]; @@ -367,6 +368,18 @@ static void sha1_object(const void *data, unsigned long size, SHA1_Update(&ctx, header, header_size); SHA1_Update(&ctx, data, size); SHA1_Final(sha1, &ctx); + + if (test_for_collision && has_sha1_file(sha1)) { + void *has_data; + enum object_type has_type; + unsigned long has_size; + has_data = read_sha1_file(sha1, &has_type, &has_size); + if (!has_data) + die("cannot read existing object %s", sha1_to_hex(sha1)); + if (size != has_size || type != has_type || + memcmp(data, has_data, size) != 0) + die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1)); + } } static void resolve_delta(struct object_entry *delta_obj, void *base_data, @@ -387,7 +400,7 @@ static void resolve_delta(struct object_entry *delta_obj, void *base_data, free(delta_data); if (!result) bad_object(delta_obj->offset, "failed to apply delta"); - sha1_object(result, result_size, type, delta_obj->sha1); + sha1_object(result, result_size, type, delta_obj->sha1, 1); nr_resolved_deltas++; hashcpy(delta_base.sha1, delta_obj->sha1); @@ -444,7 +457,7 @@ static void parse_pack_objects(unsigned char *sha1) delta->obj_no = i; delta++; } else - sha1_object(data, obj->size, obj->type, obj->sha1); + sha1_object(data, obj->size, obj->type, obj->sha1, 1); free(data); if (verbose) percent = display_progress(i+1, nr_objects, percent); @@ -565,7 +578,7 @@ static void append_obj_to_pack(void *buf, write_or_die(output_fd, header, n); obj[1].offset = obj[0].offset + n; obj[1].offset += write_compressed(output_fd, buf, size); - sha1_object(buf, size, type, obj->sha1); + sha1_object(buf, size, type, obj->sha1, 0); } static int delta_pos_compare(const void *_a, const void *_b) diff --git a/t/t5300-pack-object.sh b/t/t5300-pack-object.sh index eacb1e92c2..35e036a864 100755 --- a/t/t5300-pack-object.sh +++ b/t/t5300-pack-object.sh @@ -255,4 +255,14 @@ test_expect_success \ :' +test_expect_success \ + 'fake a SHA1 hash collision' \ + 'test -f .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67 && + cp -f .git/objects/9d/235ed07cd19811a6ceb342de82f190e49c9f68 \ + .git/objects/c8/2de19312b6c3695c0c18f70709a6c535682a67' + +test_expect_failure \ + 'make sure index-pack detects the SHA1 collision' \ + 'git-index-pack -o bad.idx test-3.pack' + test_done From ce9fbf16e0000ecca92870a90e4b30afcb3917b7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 20 Mar 2007 16:02:09 -0400 Subject: [PATCH 022/130] index-pack: use hash_sha1_file() Use hash_sha1_file() instead of duplicating code to compute object SHA1. While at it make it accept a const pointer. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- cache.h | 2 +- index-pack.c | 21 +-------------------- sha1_file.c | 4 ++-- 3 files changed, 4 insertions(+), 23 deletions(-) diff --git a/cache.h b/cache.h index 1b50a742a3..384b260227 100644 --- a/cache.h +++ b/cache.h @@ -283,7 +283,7 @@ char *enter_repo(char *path, int strict); /* Read and unpack a sha1 file into memory, write memory to a sha1 file */ extern int sha1_object_info(const unsigned char *, unsigned long *); extern void * read_sha1_file(const unsigned char *sha1, enum object_type *type, unsigned long *size); -extern int hash_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *sha1); +extern int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1); extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1); extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); diff --git a/index-pack.c b/index-pack.c index 4effb2da6d..f314937a5b 100644 --- a/index-pack.c +++ b/index-pack.c @@ -348,26 +348,7 @@ static void sha1_object(const void *data, unsigned long size, enum object_type type, unsigned char *sha1, int test_for_collision) { - SHA_CTX ctx; - char header[50]; - int header_size; - const char *type_str; - - switch (type) { - case OBJ_COMMIT: type_str = commit_type; break; - case OBJ_TREE: type_str = tree_type; break; - case OBJ_BLOB: type_str = blob_type; break; - case OBJ_TAG: type_str = tag_type; break; - default: - die("bad type %d", type); - } - - header_size = sprintf(header, "%s %lu", type_str, size) + 1; - - SHA1_Init(&ctx); - SHA1_Update(&ctx, header, header_size); - SHA1_Update(&ctx, data, size); - SHA1_Final(sha1, &ctx); + hash_sha1_file(data, size, typename(type), sha1); if (test_for_collision && has_sha1_file(sha1)) { void *has_data; diff --git a/sha1_file.c b/sha1_file.c index c445a24718..64d9813a92 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1808,7 +1808,7 @@ void *read_object_with_reference(const unsigned char *sha1, } } -static void write_sha1_file_prepare(void *buf, unsigned long len, +static void write_sha1_file_prepare(const void *buf, unsigned long len, const char *type, unsigned char *sha1, char *hdr, int *hdrlen) { @@ -1936,7 +1936,7 @@ static void setup_object_header(z_stream *stream, const char *type, unsigned lon stream->avail_out -= hdrlen; } -int hash_sha1_file(void *buf, unsigned long len, const char *type, +int hash_sha1_file(const void *buf, unsigned long len, const char *type, unsigned char *sha1) { char hdr[32]; From 9096c660a85c4a3d30f8885c766c34ce0766e869 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 20 Mar 2007 17:07:48 -0400 Subject: [PATCH 023/130] index-pack: more validation checks and cleanups When appending objects to a pack, make sure the appended data is really what we expect instead of simply loading potentially corrupted objects and legitimating them by computing a SHA1 of that corrupt data. With this the sha1_object() can lose its test_for_collision parameter which is now redundent. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- index-pack.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/index-pack.c b/index-pack.c index f314937a5b..61eb20e45b 100644 --- a/index-pack.c +++ b/index-pack.c @@ -345,12 +345,10 @@ static int find_delta_children(const union delta_base *base, } static void sha1_object(const void *data, unsigned long size, - enum object_type type, unsigned char *sha1, - int test_for_collision) + enum object_type type, unsigned char *sha1) { hash_sha1_file(data, size, typename(type), sha1); - - if (test_for_collision && has_sha1_file(sha1)) { + if (has_sha1_file(sha1)) { void *has_data; enum object_type has_type; unsigned long has_size; @@ -381,7 +379,7 @@ static void resolve_delta(struct object_entry *delta_obj, void *base_data, free(delta_data); if (!result) bad_object(delta_obj->offset, "failed to apply delta"); - sha1_object(result, result_size, type, delta_obj->sha1, 1); + sha1_object(result, result_size, type, delta_obj->sha1); nr_resolved_deltas++; hashcpy(delta_base.sha1, delta_obj->sha1); @@ -438,7 +436,7 @@ static void parse_pack_objects(unsigned char *sha1) delta->obj_no = i; delta++; } else - sha1_object(data, obj->size, obj->type, obj->sha1, 1); + sha1_object(data, obj->size, obj->type, obj->sha1); free(data); if (verbose) percent = display_progress(i+1, nr_objects, percent); @@ -541,7 +539,7 @@ static int write_compressed(int fd, void *in, unsigned int size) return size; } -static void append_obj_to_pack(void *buf, +static void append_obj_to_pack(const unsigned char *sha1, void *buf, unsigned long size, enum object_type type) { struct object_entry *obj = &objects[nr_objects++]; @@ -559,7 +557,7 @@ static void append_obj_to_pack(void *buf, write_or_die(output_fd, header, n); obj[1].offset = obj[0].offset + n; obj[1].offset += write_compressed(output_fd, buf, size); - sha1_object(buf, size, type, obj->sha1, 0); + hashcpy(obj->sha1, sha1); } static int delta_pos_compare(const void *_a, const void *_b) @@ -612,7 +610,9 @@ static void fix_unresolved_deltas(int nr_unresolved) resolve_delta(child, data, size, type); } - append_obj_to_pack(data, size, type); + if (check_sha1_signature(d->base.sha1, data, size, typename(type))) + die("local object %s is corrupt", sha1_to_hex(d->base.sha1)); + append_obj_to_pack(d->base.sha1, data, size, type); free(data); if (verbose) percent = display_progress(nr_resolved_deltas, From acdeec62cb644e48436bbe931e69b3d4842344cb Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 20 Mar 2007 10:05:20 -0700 Subject: [PATCH 024/130] Don't ever return corrupt objects from "parse_object()" Looking at the SHA1 validation code due to the corruption that Alexander Litvinov is seeing under Cygwin, I notice that one of the most central places where we read objects, we actually do end up verifying the SHA1 of the result, but then we happily parse it anyway. And using "printf" to write the error message means that it not only can get lost, but will actually mess up stdout, and cause other strange and hard-to-debug failures downstream. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- object.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/object.c b/object.c index 5b46889342..78a44a6ef4 100644 --- a/object.c +++ b/object.c @@ -184,8 +184,10 @@ struct object *parse_object(const unsigned char *sha1) if (buffer) { struct object *obj; - if (check_sha1_signature(sha1, buffer, size, typename(type)) < 0) - printf("sha1 mismatch %s\n", sha1_to_hex(sha1)); + if (check_sha1_signature(sha1, buffer, size, typename(type)) < 0) { + error("sha1 mismatch %s\n", sha1_to_hex(sha1)); + return NULL; + } obj = parse_object_buffer(sha1, type, size, buffer, &eaten); if (!eaten) From ac54c277f05c65f441efdc1b9cd7a04aaa6cf75a Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 20 Mar 2007 11:38:34 -0700 Subject: [PATCH 025/130] Be more careful about zlib return values When creating a new object, we use "deflate(stream, Z_FINISH)" in a loop until it no longer returns Z_OK, and then we do "deflateEnd()" to finish up business. That should all work, but the fact is, it's not how you're _supposed_ to use the zlib return values properly: - deflate() should never return Z_OK in the first place, except if we need to increase the output buffer size (which we're not doing, and should never need to do, since we pre-allocated a buffer that is supposed to be able to hold the output in full). So the "while()" loop was incorrect: Z_OK doesn't actually mean "ok, continue", it means "ok, allocate more memory for me and continue"! - if we got an error return, we would consider it to be end-of-stream, but it could be some internal zlib error. In short, we should check for Z_STREAM_END explicitly, since that's the only valid return value anyway for the Z_FINISH case. - we never checked deflateEnd() return codes at all. Now, admittedly, none of these issues should ever happen, unless there is some internal bug in zlib. So this patch should make zero difference, but it seems to be the right thing to do. We should probablybe anal and check the return value of "deflateInit()" too! Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- sha1_file.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index 64d9813a92..940bab5612 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1947,7 +1947,7 @@ int hash_sha1_file(const void *buf, unsigned long len, const char *type, int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1) { - int size; + int size, ret; unsigned char *compressed; z_stream stream; unsigned char sha1[20]; @@ -2007,9 +2007,14 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha /* Then the data itself.. */ stream.next_in = buf; stream.avail_in = len; - while (deflate(&stream, Z_FINISH) == Z_OK) - /* nothing */; - deflateEnd(&stream); + ret = deflate(&stream, Z_FINISH); + if (ret != Z_STREAM_END) + die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret); + + ret = deflateEnd(&stream); + if (ret != Z_OK) + die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret); + size = stream.total_out; if (write_buffer(fd, compressed, size) < 0) From 57216856999babf6f90235cf6c41dfcef98a3dab Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 20 Mar 2007 22:26:47 -0400 Subject: [PATCH 026/130] improve checkout message when asking for same branch Change the feedback message if doing 'git checkout foo' when already on branch "foo". Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- git-checkout.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/git-checkout.sh b/git-checkout.sh index 39ffa8b8a3..3c9b1bb05a 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -250,8 +250,13 @@ if [ "$?" -eq 0 ]; then if test -n "$branch" then GIT_DIR="$GIT_DIR" git-symbolic-ref -m "checkout: moving to $branch" HEAD "refs/heads/$branch" - if test -z "$quiet" + if test -n "$quiet" then + true # nothing + elif test "refs/heads/$branch" = "$oldbranch" + then + echo >&2 "Already on branch \"$branch\"" + else echo >&2 "Switched to${newbranch:+ a new} branch \"$branch\"" fi elif test -n "$detached" From 3254d218b4f9ef1550d1d83670fad8f455b08578 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 20 Mar 2007 23:32:13 -0400 Subject: [PATCH 027/130] minor git-prune optimization Don't try to remove the containing directory for every pruned object but try only once after the directory has been scanned instead. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- builtin-prune.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin-prune.c b/builtin-prune.c index 09864b7a6d..44df59e4a7 100644 --- a/builtin-prune.c +++ b/builtin-prune.c @@ -14,10 +14,8 @@ static int prune_object(char *path, const char *filename, const unsigned char *s enum object_type type = sha1_object_info(sha1, NULL); printf("%s %s\n", sha1_to_hex(sha1), (type > 0) ? typename(type) : "unknown"); - return 0; - } - unlink(mkpath("%s/%s", path, filename)); - rmdir(path); + } else + unlink(mkpath("%s/%s", path, filename)); return 0; } @@ -60,6 +58,8 @@ static int prune_dir(int i, char *path) } fprintf(stderr, "bad sha1 file: %s/%s\n", path, de->d_name); } + if (!show_only) + rmdir(path); closedir(dir); return 0; } From 171dccd511bb4642e4491dc5115549b67a859a5b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 20 Mar 2007 23:37:51 -0700 Subject: [PATCH 028/130] blame: cmp_suspect is not "cmp" anymore. The earlier round makes the function return "is it different" and it does not return a value suitable for sorting anymore. Reverse the logic to return "are they the same suspect" instead, and rename it to "same_suspect()". Signed-off-by: Junio C Hamano --- builtin-blame.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index 104521e673..60ec5354f1 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -180,15 +180,15 @@ struct scoreboard { int *lineno; }; -static int cmp_suspect(struct origin *a, struct origin *b) +static inline int same_suspect(struct origin *a, struct origin *b) { - if (a->commit != b->commit) + if (a == b) return 1; - return strcmp(a->path, b->path); + if (a->commit != b->commit) + return 0; + return !strcmp(a->path, b->path); } -#define cmp_suspect(a, b) ( ((a)==(b)) ? 0 : cmp_suspect(a,b) ) - static void sanity_check_refcnt(struct scoreboard *); /* @@ -201,7 +201,7 @@ static void coalesce(struct scoreboard *sb) struct blame_entry *ent, *next; for (ent = sb->ent; ent && (next = ent->next); ent = next) { - if (!cmp_suspect(ent->suspect, next->suspect) && + if (same_suspect(ent->suspect, next->suspect) && ent->guilty == next->guilty && ent->s_lno + ent->num_lines == next->s_lno) { ent->num_lines += next->num_lines; @@ -774,7 +774,7 @@ static int find_last_in_target(struct scoreboard *sb, struct origin *target) int last_in_target = -1; for (e = sb->ent; e; e = e->next) { - if (e->guilty || cmp_suspect(e->suspect, target)) + if (e->guilty || !same_suspect(e->suspect, target)) continue; if (last_in_target < e->s_lno + e->num_lines) last_in_target = e->s_lno + e->num_lines; @@ -794,7 +794,7 @@ static void blame_chunk(struct scoreboard *sb, struct blame_entry *e; for (e = sb->ent; e; e = e->next) { - if (e->guilty || cmp_suspect(e->suspect, target)) + if (e->guilty || !same_suspect(e->suspect, target)) continue; if (same <= e->s_lno) continue; @@ -969,7 +969,7 @@ static int find_move_in_parent(struct scoreboard *sb, while (made_progress) { made_progress = 0; for (e = sb->ent; e; e = e->next) { - if (e->guilty || cmp_suspect(e->suspect, target)) + if (e->guilty || !same_suspect(e->suspect, target)) continue; find_copy_in_blob(sb, e, parent, split, &file_p); if (split[1].suspect && @@ -1001,12 +1001,12 @@ static struct blame_list *setup_blame_list(struct scoreboard *sb, struct blame_list *blame_list = NULL; for (e = sb->ent, num_ents = 0; e; e = e->next) - if (!e->guilty && !cmp_suspect(e->suspect, target)) + if (!e->guilty && same_suspect(e->suspect, target)) num_ents++; if (num_ents) { blame_list = xcalloc(num_ents, sizeof(struct blame_list)); for (e = sb->ent, i = 0; e; e = e->next) - if (!e->guilty && !cmp_suspect(e->suspect, target)) + if (!e->guilty && same_suspect(e->suspect, target)) blame_list[i++].ent = e; } *num_ents_p = num_ents; @@ -1136,7 +1136,7 @@ static void pass_whole_blame(struct scoreboard *sb, origin->file.ptr = NULL; } for (e = sb->ent; e; e = e->next) { - if (cmp_suspect(e->suspect, origin)) + if (!same_suspect(e->suspect, origin)) continue; origin_incref(porigin); origin_decref(e->suspect); @@ -1442,7 +1442,7 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt) /* Take responsibility for the remaining entries */ for (ent = sb->ent; ent; ent = ent->next) - if (!cmp_suspect(ent->suspect, suspect)) + if (same_suspect(ent->suspect, suspect)) found_guilty_entry(ent); origin_decref(suspect); From a947ab79d43353ba29633f6716659d605d4600bc Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 21 Mar 2007 10:37:36 +0200 Subject: [PATCH 029/130] fix typo in git-am manpage Fix typo in git-am manpage Signed-off-by: Michael S. Tsirkin 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 4fb1d84413..13a7389867 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -70,7 +70,7 @@ default. You could use `--no-utf8` to override this. the patch. -C, -p:: - These flag are passed to the `git-apply` program that applies + These flags are passed to the `git-apply` program that applies the patch. --interactive:: From 1ce09dd6787c495986c75b37b07ba6bbf19b47da Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Mon, 19 Mar 2007 18:00:37 -0500 Subject: [PATCH 030/130] [PATCH] prefer "git COMMAND" over "git-COMMAND" in gitk Preferring git _space_ COMMAND over git _dash_ COMMAND allows the user to have only git and gitk in their path. e.g. when git and gitk are symbolic links in a personal bin directory to the real git and gitk. Signed-off-by: Paul Mackerras --- gitk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitk b/gitk index 1cd2a8f528..db28d745dc 100755 --- a/gitk +++ b/gitk @@ -1906,7 +1906,7 @@ proc do_file_hl {serial} { } else { set gdtargs [list "-S$highlight_files"] } - set cmd [concat | git-diff-tree -r -s --stdin $gdtargs] + set cmd [concat | git diff-tree -r -s --stdin $gdtargs] set filehighlight [open $cmd r+] fconfigure $filehighlight -blocking 0 fileevent $filehighlight readable readfhighlight @@ -1958,7 +1958,7 @@ proc readfhighlight {} { } if {[eof $filehighlight]} { # strange... - puts "oops, git-diff-tree died" + puts "oops, git diff-tree died" catch {close $filehighlight} unset filehighlight } From a8c40471ab0851bf9a58f7dc76f121258e0690e2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 21 Mar 2007 10:07:46 -0700 Subject: [PATCH 031/130] Remove "pathlen" from "struct name_entry" Since we have the "tree_entry_len()" helper function these days, and don't need to do a full strlen(), there's no point in saving the path length - it's just redundant information. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-grep.c | 2 +- builtin-pack-objects.c | 2 +- merge-tree.c | 9 +++++---- tree-walk.c | 6 ++---- tree-walk.h | 1 - tree.c | 9 +++++---- 6 files changed, 14 insertions(+), 15 deletions(-) diff --git a/builtin-grep.c b/builtin-grep.c index 4510d35324..1348cc92ef 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -378,7 +378,7 @@ static int grep_tree(struct grep_opt *opt, const char **paths, * decide if we want to descend into "abc" * directory. */ - strcpy(path_buf + len + entry.pathlen, "/"); + strcpy(path_buf + len + tree_entry_len(entry.path, entry.sha1), "/"); if (!pathspec_matches(paths, down)) ; diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 73d448b890..9231b6564f 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -854,7 +854,7 @@ static void add_pbase_object(struct tree_desc *tree, unsigned long size; enum object_type type; - if (entry.pathlen != cmplen || + if (tree_entry_len(entry.path, entry.sha1) != cmplen || memcmp(entry.path, name, cmplen) || !has_sha1_file(entry.sha1) || (type = sha1_object_info(entry.sha1, &size)) < 0) diff --git a/merge-tree.c b/merge-tree.c index b2867ba722..3b8d9e6887 100644 --- a/merge-tree.c +++ b/merge-tree.c @@ -188,7 +188,7 @@ static void resolve(const char *base, struct name_entry *branch1, struct name_en static int unresolved_directory(const char *base, struct name_entry n[3]) { - int baselen; + int baselen, pathlen; char *newbase; struct name_entry *p; struct tree_desc t[3]; @@ -205,10 +205,11 @@ static int unresolved_directory(const char *base, struct name_entry n[3]) if (!S_ISDIR(p->mode)) return 0; baselen = strlen(base); - newbase = xmalloc(baselen + p->pathlen + 2); + pathlen = tree_entry_len(p->path, p->sha1); + newbase = xmalloc(baselen + pathlen + 2); memcpy(newbase, base, baselen); - memcpy(newbase + baselen, p->path, p->pathlen); - memcpy(newbase + baselen + p->pathlen, "/", 2); + memcpy(newbase + baselen, p->path, pathlen); + memcpy(newbase + baselen + pathlen, "/", 2); buf0 = fill_tree_descriptor(t+0, n[0].sha1); buf1 = fill_tree_descriptor(t+1, n[1].sha1); diff --git a/tree-walk.c b/tree-walk.c index a4a4e2a989..1869baede5 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -20,8 +20,8 @@ void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) static int entry_compare(struct name_entry *a, struct name_entry *b) { return base_name_compare( - a->path, a->pathlen, a->mode, - b->path, b->pathlen, b->mode); + a->path, tree_entry_len(a->path, a->sha1), a->mode, + b->path, tree_entry_len(b->path, b->sha1), b->mode); } static void entry_clear(struct name_entry *a) @@ -32,7 +32,6 @@ static void entry_clear(struct name_entry *a) static void entry_extract(struct tree_desc *t, struct name_entry *a) { a->sha1 = tree_entry_extract(t, &a->path, &a->mode); - a->pathlen = tree_entry_len(a->path, a->sha1); } void update_tree_entry(struct tree_desc *desc) @@ -93,7 +92,6 @@ int tree_entry(struct tree_desc *desc, struct name_entry *entry) entry->path = path; len = strlen(path); - entry->pathlen = len; path += len + 1; entry->sha1 = (const unsigned char *) path; diff --git a/tree-walk.h b/tree-walk.h index a0d7afd89b..149393aaa4 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -10,7 +10,6 @@ struct name_entry { const unsigned char *sha1; const char *path; unsigned int mode; - int pathlen; }; static inline int tree_entry_len(const char *name, const unsigned char *sha1) diff --git a/tree.c b/tree.c index 24f8fb6766..705a481255 100644 --- a/tree.c +++ b/tree.c @@ -101,14 +101,15 @@ int read_tree_recursive(struct tree *tree, if (S_ISDIR(entry.mode)) { int retval; char *newbase; + unsigned int pathlen = tree_entry_len(entry.path, entry.sha1); - newbase = xmalloc(baselen + 1 + entry.pathlen); + newbase = xmalloc(baselen + 1 + pathlen); memcpy(newbase, base, baselen); - memcpy(newbase + baselen, entry.path, entry.pathlen); - newbase[baselen + entry.pathlen] = '/'; + memcpy(newbase + baselen, entry.path, pathlen); + newbase[baselen + pathlen] = '/'; retval = read_tree_recursive(lookup_tree(entry.sha1), newbase, - baselen + entry.pathlen + 1, + baselen + pathlen + 1, stage, match, fn); free(newbase); if (retval) From 6fda5e5180c2e7c130978361aea53b4e66f36823 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 21 Mar 2007 10:08:25 -0700 Subject: [PATCH 032/130] Initialize tree descriptors with a helper function rather than by hand. This removes slightly more lines than it adds, but the real reason for doing this is that future optimizations will require more setup of the tree descriptor, and so we want to do it in one place. Also renamed the "desc.buf" field to "desc.buffer" just to trigger compiler errors for old-style manual initializations, making sure I didn't miss anything. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-fsck.c | 5 ++--- builtin-grep.c | 11 +++++++---- builtin-pack-objects.c | 6 ++---- builtin-read-tree.c | 3 +-- builtin-reflog.c | 10 +++++----- fetch.c | 3 +-- http-push.c | 3 +-- list-objects.c | 3 +-- reachable.c | 3 +-- revision.c | 12 +++++------- tree-diff.c | 22 ++++++++++++---------- tree-walk.c | 24 +++++++++++++++--------- tree-walk.h | 5 +++-- tree.c | 9 +++------ unpack-trees.c | 3 +-- 15 files changed, 60 insertions(+), 62 deletions(-) diff --git a/builtin-fsck.c b/builtin-fsck.c index b8e71b640b..21f1f9e91d 100644 --- a/builtin-fsck.c +++ b/builtin-fsck.c @@ -227,8 +227,7 @@ static int fsck_tree(struct tree *item) const char *o_name; const unsigned char *o_sha1; - desc.buf = item->buffer; - desc.size = item->size; + init_tree_desc(&desc, item->buffer, item->size); o_mode = 0; o_name = NULL; @@ -242,7 +241,7 @@ static int fsck_tree(struct tree *item) if (strchr(name, '/')) has_full_path = 1; - has_zero_pad |= *(char *)desc.buf == '0'; + has_zero_pad |= *(char *)desc.buffer == '0'; update_tree_entry(&desc); switch (mode) { diff --git a/builtin-grep.c b/builtin-grep.c index 1348cc92ef..981f3d4d8e 100644 --- a/builtin-grep.c +++ b/builtin-grep.c @@ -388,11 +388,13 @@ static int grep_tree(struct grep_opt *opt, const char **paths, enum object_type type; struct tree_desc sub; void *data; - data = read_sha1_file(entry.sha1, &type, &sub.size); + unsigned long size; + + data = read_sha1_file(entry.sha1, &type, &size); if (!data) die("unable to read tree (%s)", sha1_to_hex(entry.sha1)); - sub.buf = data; + init_tree_desc(&sub, data, size); hit |= grep_tree(opt, paths, &sub, tree_name, down); free(data); } @@ -408,12 +410,13 @@ static int grep_object(struct grep_opt *opt, const char **paths, if (obj->type == OBJ_COMMIT || obj->type == OBJ_TREE) { struct tree_desc tree; void *data; + unsigned long size; int hit; data = read_object_with_reference(obj->sha1, tree_type, - &tree.size, NULL); + &size, NULL); if (!data) die("unable to read tree (%s)", sha1_to_hex(obj->sha1)); - tree.buf = data; + init_tree_desc(&tree, data, size); hit = grep_tree(opt, paths, &tree, name, ""); free(data); return hit; diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 9231b6564f..b5f9648e80 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -873,8 +873,7 @@ static void add_pbase_object(struct tree_desc *tree, tree = pbase_tree_get(entry.sha1); if (!tree) return; - sub.buf = tree->tree_data; - sub.size = tree->tree_size; + init_tree_desc(&sub, tree->tree_data, tree->tree_size); add_pbase_object(&sub, down, downlen, fullname); pbase_tree_put(tree); @@ -937,8 +936,7 @@ static void add_preferred_base_object(const char *name, unsigned hash) } else { struct tree_desc tree; - tree.buf = it->pcache.tree_data; - tree.size = it->pcache.tree_size; + init_tree_desc(&tree, it->pcache.tree_data, it->pcache.tree_size); add_pbase_object(&tree, name, cmplen, name); } } diff --git a/builtin-read-tree.c b/builtin-read-tree.c index e47715538b..82df94101a 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -55,8 +55,7 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree) int cnt; hashcpy(it->sha1, tree->object.sha1); - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); cnt = 0; while (tree_entry(&desc, &entry)) { if (!S_ISDIR(entry.mode)) diff --git a/builtin-reflog.c b/builtin-reflog.c index 186aabce04..4c39f1da98 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -52,18 +52,18 @@ static int tree_is_complete(const unsigned char *sha1) if (tree->object.flags & INCOMPLETE) return 0; - desc.buf = tree->buffer; - desc.size = tree->size; - if (!desc.buf) { + if (!tree->buffer) { enum object_type type; - void *data = read_sha1_file(sha1, &type, &desc.size); + unsigned long size; + void *data = read_sha1_file(sha1, &type, &size); if (!data) { tree->object.flags |= INCOMPLETE; return 0; } - desc.buf = data; tree->buffer = data; + tree->size = size; } + init_tree_desc(&desc, tree->buffer, tree->size); complete = 1; while (tree_entry(&desc, &entry)) { if (!has_sha1_file(entry.sha1) || diff --git a/fetch.c b/fetch.c index f69be82f10..8e29d313f8 100644 --- a/fetch.c +++ b/fetch.c @@ -42,8 +42,7 @@ static int process_tree(struct tree *tree) if (parse_tree(tree)) return -1; - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { struct object *obj = NULL; diff --git a/http-push.c b/http-push.c index cbb02d3bc1..724720c562 100644 --- a/http-push.c +++ b/http-push.c @@ -1750,8 +1750,7 @@ static struct object_list **process_tree(struct tree *tree, me.elem = name; me.elem_len = strlen(name); - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (S_ISDIR(entry.mode)) diff --git a/list-objects.c b/list-objects.c index f1fa21c397..2ba2c958e0 100644 --- a/list-objects.c +++ b/list-objects.c @@ -49,8 +49,7 @@ static void process_tree(struct rev_info *revs, me.elem = name; me.elem_len = strlen(name); - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (S_ISDIR(entry.mode)) diff --git a/reachable.c b/reachable.c index 01760d7046..ff3dd34962 100644 --- a/reachable.c +++ b/reachable.c @@ -42,8 +42,7 @@ static void process_tree(struct tree *tree, me.elem = name; me.elem_len = strlen(name); - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (S_ISDIR(entry.mode)) diff --git a/revision.c b/revision.c index c680dcb8ba..adc381c268 100644 --- a/revision.c +++ b/revision.c @@ -62,8 +62,7 @@ void mark_tree_uninteresting(struct tree *tree) if (parse_tree(tree) < 0) die("bad tree %s", sha1_to_hex(obj->sha1)); - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (S_ISDIR(entry.mode)) mark_tree_uninteresting(lookup_tree(entry.sha1)); @@ -275,18 +274,17 @@ int rev_same_tree_as_empty(struct rev_info *revs, struct tree *t1) { int retval; void *tree; + unsigned long size; struct tree_desc empty, real; if (!t1) return 0; - tree = read_object_with_reference(t1->object.sha1, tree_type, &real.size, NULL); + tree = read_object_with_reference(t1->object.sha1, tree_type, &size, NULL); if (!tree) return 0; - real.buf = tree; - - empty.buf = ""; - empty.size = 0; + init_tree_desc(&real, tree, size); + init_tree_desc(&empty, "", 0); tree_difference = REV_TREE_SAME; revs->pruning.has_changes = 0; diff --git a/tree-diff.c b/tree-diff.c index b2f35dc3d8..36788058ae 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -154,12 +154,13 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree char *newbase = malloc_base(base, baselen, path, pathlen); struct tree_desc inner; void *tree; + unsigned long size; - tree = read_sha1_file(sha1, &type, &inner.size); + tree = read_sha1_file(sha1, &type, &size); if (!tree || type != OBJ_TREE) die("corrupt tree sha %s", sha1_to_hex(sha1)); - inner.buf = tree; + init_tree_desc(&inner, tree, size); show_tree(opt, prefix, &inner, newbase, baselen + 1 + pathlen); free(tree); @@ -227,16 +228,17 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha { void *tree1, *tree2; struct tree_desc t1, t2; + unsigned long size1, size2; int retval; - tree1 = read_object_with_reference(old, tree_type, &t1.size, NULL); + tree1 = read_object_with_reference(old, tree_type, &size1, NULL); if (!tree1) die("unable to read source tree (%s)", sha1_to_hex(old)); - tree2 = read_object_with_reference(new, tree_type, &t2.size, NULL); + tree2 = read_object_with_reference(new, tree_type, &size2, NULL); if (!tree2) die("unable to read destination tree (%s)", sha1_to_hex(new)); - t1.buf = tree1; - t2.buf = tree2; + init_tree_desc(&t1, tree1, size1); + init_tree_desc(&t2, tree2, size2); retval = diff_tree(&t1, &t2, base, opt); free(tree1); free(tree2); @@ -247,15 +249,15 @@ int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_ { int retval; void *tree; + unsigned long size; struct tree_desc empty, real; - tree = read_object_with_reference(new, tree_type, &real.size, NULL); + tree = read_object_with_reference(new, tree_type, &size, NULL); if (!tree) die("unable to read root tree (%s)", sha1_to_hex(new)); - real.buf = tree; + init_tree_desc(&real, tree, size); - empty.size = 0; - empty.buf = ""; + init_tree_desc(&empty, "", 0); retval = diff_tree(&empty, &real, base, opt); free(tree); return retval; diff --git a/tree-walk.c b/tree-walk.c index 1869baede5..c65492c02d 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -2,6 +2,12 @@ #include "tree-walk.h" #include "tree.h" +void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size) +{ + desc->buffer = buffer; + desc->size = size; +} + void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) { unsigned long size = 0; @@ -12,8 +18,7 @@ void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) if (!buf) die("unable to read tree %s", sha1_to_hex(sha1)); } - desc->size = size; - desc->buf = buf; + init_tree_desc(desc, buf, size); return buf; } @@ -36,13 +41,13 @@ static void entry_extract(struct tree_desc *t, struct name_entry *a) void update_tree_entry(struct tree_desc *desc) { - const void *buf = desc->buf; + const void *buf = desc->buffer; unsigned long size = desc->size; int len = strlen(buf) + 1 + 20; if (size < len) die("corrupt tree file"); - desc->buf = (char *) buf + len; + desc->buffer = (char *) buf + len; desc->size = size - len; } @@ -62,7 +67,7 @@ static const char *get_mode(const char *str, unsigned int *modep) const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep) { - const void *tree = desc->buf; + const void *tree = desc->buffer; unsigned long size = desc->size; int len = strlen(tree)+1; const unsigned char *sha1 = (unsigned char *) tree + len; @@ -79,7 +84,7 @@ const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pat int tree_entry(struct tree_desc *desc, struct name_entry *entry) { - const void *tree = desc->buf; + const void *tree = desc->buffer; const char *path; unsigned long len, size = desc->size; @@ -101,7 +106,7 @@ int tree_entry(struct tree_desc *desc, struct name_entry *entry) if (len > size) die("corrupt tree file"); - desc->buf = path; + desc->buffer = path; desc->size = size - len; return 1; } @@ -196,10 +201,11 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch { int retval; void *tree; + unsigned long size; struct tree_desc t; unsigned char root[20]; - tree = read_object_with_reference(tree_sha1, tree_type, &t.size, root); + tree = read_object_with_reference(tree_sha1, tree_type, &size, root); if (!tree) return -1; @@ -208,7 +214,7 @@ int get_tree_entry(const unsigned char *tree_sha1, const char *name, unsigned ch return 0; } - t.buf = tree; + init_tree_desc(&t, tree, size); retval = find_tree_entry(&t, name, sha1, mode); free(tree); return retval; diff --git a/tree-walk.h b/tree-walk.h index 149393aaa4..ca0c29fb1a 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -2,8 +2,8 @@ #define TREE_WALK_H struct tree_desc { - const void *buf; - unsigned long size; + const void *buffer; + unsigned int size; }; struct name_entry { @@ -18,6 +18,7 @@ static inline int tree_entry_len(const char *name, const unsigned char *sha1) } void update_tree_entry(struct tree_desc *); +void init_tree_desc(struct tree_desc *desc, const void *buf, unsigned long size); const unsigned char *tree_entry_extract(struct tree_desc *, const char **, unsigned int *); /* Helper function that does both of the above and returns true for success */ diff --git a/tree.c b/tree.c index 705a481255..d188c0fbae 100644 --- a/tree.c +++ b/tree.c @@ -83,8 +83,7 @@ int read_tree_recursive(struct tree *tree, if (parse_tree(tree)) return -1; - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &entry)) { if (!match_tree_entry(base, baselen, entry.path, entry.mode, match)) @@ -152,16 +151,14 @@ static void track_tree_refs(struct tree *item) struct name_entry entry; /* Count how many entries there are.. */ - desc.buf = item->buffer; - desc.size = item->size; + init_tree_desc(&desc, item->buffer, item->size); while (tree_entry(&desc, &entry)) n_refs++; /* Allocate object refs and walk it again.. */ i = 0; refs = alloc_object_refs(n_refs); - desc.buf = item->buffer; - desc.size = item->size; + init_tree_desc(&desc, item->buffer, item->size); while (tree_entry(&desc, &entry)) { struct object *obj; diff --git a/unpack-trees.c b/unpack-trees.c index 2e2232cbb0..ee10eea24c 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -27,8 +27,7 @@ static struct tree_entry_list *create_tree_entry_list(struct tree *tree) if (!tree->object.parsed) parse_tree(tree); - desc.buf = tree->buffer; - desc.size = tree->size; + init_tree_desc(&desc, tree->buffer, tree->size); while (tree_entry(&desc, &one)) { struct tree_entry_list *entry; From 4651ece8540a90a42af355e995847fb89192cc81 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 21 Mar 2007 10:09:56 -0700 Subject: [PATCH 033/130] Switch over tree descriptors to contain a pre-parsed entry This makes the tree descriptor contain a "struct name_entry" as part of it, and it gets filled in so that it always contains a valid entry. On some benchmarks, it improves performance by up to 15%. That makes tree entry "extract" trivial, and means that we only actually need to decode each tree entry just once: we decode the first one when we initialize the tree descriptor, and each subsequent one when doing "update_tree_entry()". In particular, this means that we don't need to do strlen() both at extract time _and_ at update time. Finally, it also allows more sharing of code (entry_extract(), that wanted a "struct name_entry", just got totally trivial, along with the "tree_entry()" function). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- tree-walk.c | 101 +++++++++++++++++++++++----------------------------- tree-walk.h | 18 +++++++--- 2 files changed, 57 insertions(+), 62 deletions(-) diff --git a/tree-walk.c b/tree-walk.c index c65492c02d..cbb24eb3f6 100644 --- a/tree-walk.c +++ b/tree-walk.c @@ -2,10 +2,42 @@ #include "tree-walk.h" #include "tree.h" +static const char *get_mode(const char *str, unsigned int *modep) +{ + unsigned char c; + unsigned int mode = 0; + + while ((c = *str++) != ' ') { + if (c < '0' || c > '7') + return NULL; + mode = (mode << 3) + (c - '0'); + } + *modep = mode; + return str; +} + +static void decode_tree_entry(struct tree_desc *desc, const void *buf, unsigned long size) +{ + const char *path; + unsigned int mode, len; + + path = get_mode(buf, &mode); + if (!path) + die("corrupt tree file"); + len = strlen(path) + 1; + + /* Initialize the descriptor entry */ + desc->entry.path = path; + desc->entry.mode = mode; + desc->entry.sha1 = (const unsigned char *)(path + len); +} + void init_tree_desc(struct tree_desc *desc, const void *buffer, unsigned long size) { desc->buffer = buffer; desc->size = size; + if (size) + decode_tree_entry(desc, buffer, size); } void *fill_tree_descriptor(struct tree_desc *desc, const unsigned char *sha1) @@ -36,78 +68,33 @@ static void entry_clear(struct name_entry *a) static void entry_extract(struct tree_desc *t, struct name_entry *a) { - a->sha1 = tree_entry_extract(t, &a->path, &a->mode); + *a = t->entry; } void update_tree_entry(struct tree_desc *desc) { const void *buf = desc->buffer; + const unsigned char *end = desc->entry.sha1 + 20; unsigned long size = desc->size; - int len = strlen(buf) + 1 + 20; + unsigned long len = end - (const unsigned char *)buf; if (size < len) die("corrupt tree file"); - desc->buffer = (char *) buf + len; - desc->size = size - len; -} - -static const char *get_mode(const char *str, unsigned int *modep) -{ - unsigned char c; - unsigned int mode = 0; - - while ((c = *str++) != ' ') { - if (c < '0' || c > '7') - return NULL; - mode = (mode << 3) + (c - '0'); - } - *modep = mode; - return str; -} - -const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep) -{ - const void *tree = desc->buffer; - unsigned long size = desc->size; - int len = strlen(tree)+1; - const unsigned char *sha1 = (unsigned char *) tree + len; - const char *path; - unsigned int mode; - - path = get_mode(tree, &mode); - if (!path || size < len + 20) - die("corrupt tree file"); - *pathp = path; - *modep = canon_mode(mode); - return sha1; + buf = end; + size -= len; + desc->buffer = buf; + desc->size = size; + if (size) + decode_tree_entry(desc, buf, size); } int tree_entry(struct tree_desc *desc, struct name_entry *entry) { - const void *tree = desc->buffer; - const char *path; - unsigned long len, size = desc->size; - - if (!size) + if (!desc->size) return 0; - path = get_mode(tree, &entry->mode); - if (!path) - die("corrupt tree file"); - - entry->path = path; - len = strlen(path); - - path += len + 1; - entry->sha1 = (const unsigned char *) path; - - path += 20; - len = path - (char *) tree; - if (len > size) - die("corrupt tree file"); - - desc->buffer = path; - desc->size = size - len; + *entry = desc->entry; + update_tree_entry(desc); return 1; } diff --git a/tree-walk.h b/tree-walk.h index ca0c29fb1a..43458cf8ce 100644 --- a/tree-walk.h +++ b/tree-walk.h @@ -1,17 +1,25 @@ #ifndef TREE_WALK_H #define TREE_WALK_H -struct tree_desc { - const void *buffer; - unsigned int size; -}; - struct name_entry { const unsigned char *sha1; const char *path; unsigned int mode; }; +struct tree_desc { + const void *buffer; + struct name_entry entry; + unsigned int size; +}; + +static inline const unsigned char *tree_entry_extract(struct tree_desc *desc, const char **pathp, unsigned int *modep) +{ + *pathp = desc->entry.path; + *modep = canon_mode(desc->entry.mode); + return desc->entry.sha1; +} + static inline int tree_entry_len(const char *name, const unsigned char *sha1) { return (char *)sha1 - (char *)name - 1; From 7d2f667b12334cea68087eb7da717efd7b3d80f6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 21 Mar 2007 09:51:47 -0700 Subject: [PATCH 034/130] Teach tree_entry_interesting() that the tree entries are sorted. When we are looking at a tree entry with pathspecs, if all the pathspecs sort strictly earlier than the entry we are currently looking at, there is no way later entries in the same tree would match our pathspecs, because the entries are sorted. Signed-off-by: Junio C Hamano --- tree-diff.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/tree-diff.c b/tree-diff.c index 36788058ae..35af569fb8 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -81,6 +81,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int unsigned mode; int i; int pathlen; + int never_interesting = -1; if (!opt->nr_paths) return 1; @@ -89,9 +90,10 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int pathlen = tree_entry_len(path, sha1); - for (i=0; i < opt->nr_paths; i++) { + for (i = 0; i < opt->nr_paths; i++) { const char *match = opt->paths[i]; int matchlen = opt->pathlens[i]; + int m; if (baselen >= matchlen) { /* If it doesn't match, move along... */ @@ -109,6 +111,30 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int match += baselen; matchlen -= baselen; + /* + * Does match sort strictly earlier than path with their + * common parts? + */ + m = strncmp(match, path, + (matchlen < pathlen) ? matchlen : pathlen); + if (m < 0) + continue; + + /* + * If we come here even once, that means there is at + * least one pathspec that would sort equal to or + * later than the path we are currently looking at. + * In other words, if we have never reached this point + * after iterating all pathspecs, it means all + * pathspecs are either outside of base, or inside the + * base but sorts strictly earlier than the current + * one. In either case, they will never match the + * subsequent entries. In such a case, we initialized + * the variable to -1 and that is what will be + * returned, allowing the caller to terminate early. + */ + never_interesting = 0; + if (pathlen > matchlen) continue; @@ -119,12 +145,15 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int continue; } - if (strncmp(path, match, pathlen)) - continue; - - return 1; + /* + * If common part matched earlier then it is a hit, + * because we rejected the case where path is not a + * leading directory and is shorter than match. + */ + if (!m) + return 1; } - return 0; /* No matches */ + return never_interesting; /* No matches */ } /* A whole sub-tree went away or appeared */ From ccc744abbb27d3766175aee971991bc0f1fd4f00 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 21 Mar 2007 12:34:46 -0700 Subject: [PATCH 035/130] tree-diff: avoid strncmp() If we already know that some of the pathspecs can match later entries in the tree we are looking at, we do not have to do more expensive strncmp() upfront before comparing the length of the match pattern and the path, as a path longer than the match pattern will not match it, and a path shorter than the match pattern will match only if the path is a directory-component wise prefix of the match pattern. Signed-off-by: Junio C Hamano --- tree-diff.c | 60 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/tree-diff.c b/tree-diff.c index 35af569fb8..15fd665fb8 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -93,7 +93,7 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int for (i = 0; i < opt->nr_paths; i++) { const char *match = opt->paths[i]; int matchlen = opt->pathlens[i]; - int m; + int m = -1; /* signals that we haven't called strncmp() */ if (baselen >= matchlen) { /* If it doesn't match, move along... */ @@ -111,29 +111,36 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int match += baselen; matchlen -= baselen; - /* - * Does match sort strictly earlier than path with their - * common parts? - */ - m = strncmp(match, path, - (matchlen < pathlen) ? matchlen : pathlen); - if (m < 0) - continue; + if (never_interesting) { + /* + * We have not seen any match that sorts later + * than the current path. + */ - /* - * If we come here even once, that means there is at - * least one pathspec that would sort equal to or - * later than the path we are currently looking at. - * In other words, if we have never reached this point - * after iterating all pathspecs, it means all - * pathspecs are either outside of base, or inside the - * base but sorts strictly earlier than the current - * one. In either case, they will never match the - * subsequent entries. In such a case, we initialized - * the variable to -1 and that is what will be - * returned, allowing the caller to terminate early. - */ - never_interesting = 0; + /* + * Does match sort strictly earlier than path + * with their common parts? + */ + m = strncmp(match, path, + (matchlen < pathlen) ? matchlen : pathlen); + if (m < 0) + continue; + + /* + * If we come here even once, that means there is at + * least one pathspec that would sort equal to or + * later than the path we are currently looking at. + * In other words, if we have never reached this point + * after iterating all pathspecs, it means all + * pathspecs are either outside of base, or inside the + * base but sorts strictly earlier than the current + * one. In either case, they will never match the + * subsequent entries. In such a case, we initialized + * the variable to -1 and that is what will be + * returned, allowing the caller to terminate early. + */ + never_interesting = 0; + } if (pathlen > matchlen) continue; @@ -145,6 +152,13 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int continue; } + if (m == -1) + /* + * we cheated and did not do strncmp(), so we do + * that here. + */ + m = strncmp(match, path, pathlen); + /* * If common part matched earlier then it is a hit, * because we rejected the case where path is not a From 1d848f643cd8ba86044d729d08d6866425c1539e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 21 Mar 2007 17:00:27 -0700 Subject: [PATCH 036/130] tree_entry_interesting(): allow it to say "everything is interesting" In addition to optimizing pathspecs that would never match, which was done earlier, this optimizes pathspecs that would always match (e.g. "arch/" while the traversal is already in "arch/i386/" hierarchy). This patch makes the worst case slightly more palatable, while improving average case. Signed-off-by: Junio C Hamano --- tree-diff.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/tree-diff.c b/tree-diff.c index 15fd665fb8..852498eb49 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -70,7 +70,8 @@ static int compare_tree_entry(struct tree_desc *t1, struct tree_desc *t2, const * Is a tree entry interesting given the pathspec we have? * * Return: - * - positive for yes + * - 2 for "yes, and all subsequent entries will be" + * - 1 for yes * - zero for no * - negative for "no, and no subsequent entries will be either" */ @@ -100,8 +101,11 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int if (strncmp(base, match, matchlen)) continue; - /* The base is a subdirectory of a path which was specified. */ - return 1; + /* + * The base is a subdirectory of a path which + * was specified, so all of them are interesting. + */ + return 2; } /* Does the base match? */ @@ -173,8 +177,18 @@ static int tree_entry_interesting(struct tree_desc *desc, const char *base, int /* A whole sub-tree went away or appeared */ static void show_tree(struct diff_options *opt, const char *prefix, struct tree_desc *desc, const char *base, int baselen) { + int all_interesting = 0; while (desc->size) { - int show = tree_entry_interesting(desc, base, baselen, opt); + int show; + + if (all_interesting) + show = 1; + else { + show = tree_entry_interesting(desc, base, baselen, + opt); + if (show == 2) + all_interesting = 1; + } if (show < 0) break; if (show) @@ -215,8 +229,17 @@ static void show_entry(struct diff_options *opt, const char *prefix, struct tree static void skip_uninteresting(struct tree_desc *t, const char *base, int baselen, struct diff_options *opt) { + int all_interesting = 0; while (t->size) { - int show = tree_entry_interesting(t, base, baselen, opt); + int show; + + if (all_interesting) + show = 1; + else { + show = tree_entry_interesting(t, base, baselen, opt); + if (show == 2) + all_interesting = 1; + } if (!show) { update_tree_entry(t); continue; From a1bf91e081de236af34bf8acd484881ce146fc93 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 22 Mar 2007 02:54:59 -0700 Subject: [PATCH 037/130] git-rebase: make 'rebase HEAD branch' work as expected. When you want to amend the commit message of 3 commits before the tip of the current branch, say 'master', A--B--C--D--E(master) it is sometimes handy to make your head detached at that commit with: $ git checkout HEAD~3 ;# check out B $ git commit --amend ;# without modifying contents... to create: .B'(HEAD) / A--B--C--D--E(master) and then rebase 'master' branch onto HEAD with this: $ git rebase HEAD master to result in: .B'-C'-D'-E(master=HEAD) / A--B--C--D--E However, the current code interprets HEAD after it switches to the branch 'master', which means the rebase will not do anything. You have to say something unwieldly like this instead: $ git rebase $(git rev-parse HEAD) master This fixes it by expanding the $onto commit name before switching to the target branch. Signed-off-by: Junio C Hamano --- git-rebase.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/git-rebase.sh b/git-rebase.sh index b51d19d12e..aadd580f8d 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -265,6 +265,10 @@ upstream_name="$1" upstream=`git rev-parse --verify "${upstream_name}^0"` || die "invalid upstream $upstream_name" +# Make sure the branch to rebase onto is valid. +onto_name=${newbase-"$upstream_name"} +onto=$(git-rev-parse --verify "${onto_name}^0") || exit + # If a hook exists, give it a chance to interrupt if test -x "$GIT_DIR/hooks/pre-rebase" then @@ -291,10 +295,6 @@ case "$#" in esac branch=$(git-rev-parse --verify "${branch_name}^0") || exit -# Make sure the branch to rebase onto is valid. -onto_name=${newbase-"$upstream_name"} -onto=$(git-rev-parse --verify "${onto_name}^0") || exit - # Now we are rebasing commits $upstream..$branch on top of $onto # Check if we are already based on $onto, but this should be From 85295a52e683a24d8404c6989d8b8f134a0ea684 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 22 Mar 2007 11:07:30 +0200 Subject: [PATCH 038/130] git-merge: Put FETCH_HEAD data in merge commit message This makes git-fetch && git-merge FETCH_HEAD produce the same merge message as git-pull . Signed-off-by: Michael S. Tsirkin Signed-off-by: Junio C Hamano --- git-merge.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/git-merge.sh b/git-merge.sh index 8759c5a7e0..fa4589173f 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -108,6 +108,10 @@ merge_name () { git-show-ref -q --verify "refs/heads/$truname" 2>/dev/null then echo "$rh branch '$truname' (early part) of ." + elif test "$remote" = "FETCH_HEAD" -a -r "$GIT_DIR/FETCH_HEAD" + then + sed -e 's/ not-for-merge / /' -e 1q \ + "$GIT_DIR/FETCH_HEAD" else echo "$rh commit '$remote'" fi From 0a0d080bdc68d2bd4a1824b08123690c8065badb Mon Sep 17 00:00:00 2001 From: Andy Parkins Date: Tue, 20 Mar 2007 10:58:32 +0000 Subject: [PATCH 039/130] update-hook: abort early if the project description is unset It was annoying to always have the first email from a project be from the "Unnamed repository; edit this file to name it for gitweb project"; just because it's so easy to forget to set it. This patch checks to see if the description file is still default (or empty) and aborts if so - allowing you to fix the problem before sending out silly looking emails to every developer. Signed-off-by: Andy Parkins Signed-off-by: Junio C Hamano --- templates/hooks--update | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/templates/hooks--update b/templates/hooks--update index 8f6c4fea24..1a60773890 100644 --- a/templates/hooks--update +++ b/templates/hooks--update @@ -56,6 +56,12 @@ recipients=$(git-repo-config hooks.mailinglist) announcerecipients=$(git-repo-config hooks.announcelist) allowunannotated=$(git-repo-config --bool hooks.allowunannotated) +# check for no description +if [ -z "$projectdesc" -o "$projectdesc" = "Unnamed repository; edit this file to name it for gitweb" ]; then + echo "*** Project description file hasn't been set" >&2 + exit 1 +fi + # --- Check types newrev_type=$(git-cat-file -t $newrev) From 605fac8b5bd6d4a2ca817631e2c56ba2d0a1ed91 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 21 Mar 2007 17:11:44 -0400 Subject: [PATCH 040/130] update HEAD reflog when branch pointed to by HEAD is directly modified The HEAD reflog is updated as well as the reflog for the branch pointed to by HEAD whenever it is referenced with "HEAD". There are some cases where a specific branch may be modified directly. In those cases, the HEAD reflog should be updated as well if it is a symref to that branch in order to be consistent. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- refs.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/refs.c b/refs.c index 9f1fb68d04..f471152bfc 100644 --- a/refs.c +++ b/refs.c @@ -980,6 +980,27 @@ int write_ref_sha1(struct ref_lock *lock, unlock_ref(lock); return -1; } + if (strcmp(lock->orig_ref_name, "HEAD") != 0) { + /* + * Special hack: If a branch is updated directly and HEAD + * points to it (may happen on the remote side of a push + * for example) then logically the HEAD reflog should be + * updated too. + * A generic solution implies reverse symref information, + * but finding all symrefs pointing to the given branch + * would be rather costly for this rare event (the direct + * update of a branch) to be worth it. So let's cheat and + * check with HEAD only which should cover 99% of all usage + * scenarios (even 100% of the default ones). + */ + unsigned char head_sha1[20]; + int head_flag; + const char *head_ref; + head_ref = resolve_ref("HEAD", head_sha1, 1, &head_flag); + if (head_ref && (head_flag & REF_ISSYMREF) && + !strcmp(head_ref, lock->ref_name)) + log_ref_write("HEAD", lock->old_sha1, sha1, logmsg); + } if (commit_lock_file(lock->lk)) { error("Couldn't set %s", lock->ref_name); unlock_ref(lock); From 979ea5856cddace7223ddd715a448dbe49fcb290 Mon Sep 17 00:00:00 2001 From: Peter Eriksen Date: Wed, 21 Mar 2007 19:43:37 +0100 Subject: [PATCH 041/130] Documentation/pack-format.txt: Clear up description of types. Signed-off-by: Peter Eriksen Signed-off-by: Junio C Hamano --- Documentation/technical/pack-format.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Documentation/technical/pack-format.txt b/Documentation/technical/pack-format.txt index 0e1ffb2427..9ce3c473ae 100644 --- a/Documentation/technical/pack-format.txt +++ b/Documentation/technical/pack-format.txt @@ -21,11 +21,11 @@ GIT pack format which looks like this: (undeltified representation) - n-byte type and length (4-bit type, (n-1)*7+4-bit length) + n-byte type and length (3-bit type, (n-1)*7+4-bit length) compressed data (deltified representation) - n-byte type and length (4-bit type, (n-1)*7+4-bit length) + n-byte type and length (3-bit type, (n-1)*7+4-bit length) 20-byte base object name compressed delta data @@ -102,11 +102,13 @@ trailer | | packfile checksum | Pack file entry: <+ packed object header: - 1-byte type (upper 4-bit) + 1-byte size extension bit (MSB) + type (next 3 bit) size0 (lower 4-bit) n-byte sizeN (as long as MSB is set, each 7-bit) size0..sizeN form 4+7+7+..+7 bit integer, size0 - is the most significant part. + is the least significant part, and sizeN is the + most significant part. packed object data: If it is not DELTA, then deflated bytes (the size above is the size before compression). From cc96fd092a55a7a8685f0dee1e287ded70bc08b7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 22 Mar 2007 17:32:51 -0700 Subject: [PATCH 042/130] git-apply: Do not free the wrong buffer when we convert the data for writeout When we write out the result of patch application, we sometimes need to munge the data (e.g. under core.autocrlf). After doing so, what we should free is the temporary buffer that holds the converted data returned from convert_to_working_tree(), not the original one. This patch also moves the call to open() up in the function, as the caller expects us to fail cheaply if leading directories need to be created (and then the caller creates them and calls us again). For that calling pattern, attempting conversion before opening the file adds unnecessary overhead. Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- builtin-apply.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/builtin-apply.c b/builtin-apply.c index dfa1716796..27a182bfaa 100644 --- a/builtin-apply.c +++ b/builtin-apply.c @@ -2355,7 +2355,7 @@ static void add_index_file(const char *path, unsigned mode, void *buf, unsigned static int try_create_file(const char *path, unsigned int mode, const char *buf, unsigned long size) { - int fd; + int fd, converted; char *nbuf; unsigned long nsize; @@ -2364,17 +2364,18 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, * terminated. */ return symlink(buf, path); - nsize = size; - nbuf = (char *) buf; - if (convert_to_working_tree(path, &nbuf, &nsize)) { - free((char *) buf); - buf = nbuf; - size = nsize; - } fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666); if (fd < 0) return -1; + + nsize = size; + nbuf = (char *) buf; + converted = convert_to_working_tree(path, &nbuf, &nsize); + if (converted) { + buf = nbuf; + size = nsize; + } while (size) { int written = xwrite(fd, buf, size); if (written < 0) @@ -2386,6 +2387,8 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf, } if (close(fd) < 0) die("closing file %s: %s", path, strerror(errno)); + if (converted) + free(nbuf); return 0; } From 3007a78033fec09b97ff1ca816a2d23c292dd956 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 22 Mar 2007 21:05:28 -0400 Subject: [PATCH 043/130] t4118: be nice to non-GNU sed Elias Pipping: > I'm on a mac, hence /usr/bin/sed is not gnu sed, which makes > t4118 fail. Signed-off-by: Johannes Schindelin Ack'd-by: Elias Pipping Signed-off-by: Junio C Hamano --- t/t4118-apply-empty-context.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index 690a182003..27cc6f2b88 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -23,7 +23,8 @@ test_expect_success setup ' cat file2 >file2.orig git add file1 file2 && sed -e "/^B/d" file1 && - sed -e "/^B/d" file2 && + sed -e "/^[BQ]/d" file2 && + echo Q | tr -d "\\012" >>file2 && cat file1 >file1.mods && cat file2 >file2.mods && git diff | From cc65343a8436896f4c78f5f802595870784df454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Thu, 22 Mar 2007 17:18:08 +0100 Subject: [PATCH 044/130] Bisect: convert revs given to good and bad to commits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without this the rev could be (e.g.) a tag and then the condition to end the bisect might fail and you have to check the already known to be bad revision once more. Signed-off-by: Uwe Kleine-König Signed-off-by: Junio C Hamano --- git-bisect.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index b1c3a6b1c1..dbce0dfec9 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -85,7 +85,7 @@ bisect_bad() { 0) rev=$(git-rev-parse --verify HEAD) ;; 1) - rev=$(git-rev-parse --verify "$1") ;; + rev=$(git-rev-parse --verify "$1^{commit}") ;; *) usage ;; esac || exit @@ -104,7 +104,7 @@ bisect_good() { esac for rev in $revs do - rev=$(git-rev-parse --verify "$rev") || exit + rev=$(git-rev-parse --verify "$rev^{commit}") || exit echo "$rev" >"$GIT_DIR/refs/bisect/good-$rev" echo "# good: "$(git-show-branch $rev) >>"$GIT_DIR/BISECT_LOG" echo "git-bisect good $rev" >>"$GIT_DIR/BISECT_LOG" From a17c4101003dbadc13d404a5dd5d106de1e57a3a Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 23 Mar 2007 08:49:59 +0100 Subject: [PATCH 045/130] Bisect: implement "git bisect run ..." to automatically bisect. This idea was suggested by Bill Lear (Message-ID: <17920.38942.364466.642979@lisa.zopyra.com>) and I think it is a very good one. This patch adds a new test file for "git bisect run", but there is currently only one basic test. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 30 +++++++++++++++++++ git-bisect.sh | 54 ++++++++++++++++++++++++++++++++-- t/t6030-bisect-run.sh | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 3 deletions(-) create mode 100755 t/t6030-bisect-run.sh diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 16ec7269b2..b7cd715380 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -22,6 +22,7 @@ depending on the subcommand: git bisect visualize git bisect replay git bisect log + git bisect run ... This command uses 'git-rev-list --bisect' option to help drive the binary search process to find which change introduced a bug, @@ -121,6 +122,35 @@ like this: $ git bisect start arch/i386 include/asm-i386 ------------ +If you have a script that can tell if the current +source code is good or bad, you can automatically bisect using: + +------------ +$ git bisect run my_script +------------ + +Note that the "run" script (`my_script` in the above example) +should exit with code 0 in +case the current source code is good and with a code between 1 and 127 +(included) in case the current source code is bad. + +Any other exit code (a program that does "exit(-1)" leaves $? = 255, +see exit(3) manual page, the value is chopped with "& 0377") will +abort the automatic bisect process. + +You may often find that during bisect you want to have near-constant +tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or +"revision that does not have this commit needs this patch applied to +work around other problem this bisection is not interested in") +applied to the revision being tested. + +To cope with such a situation, after the inner git-bisect finds the +next revision to test, with the "run" script, you can apply that tweak +before compiling, run the real test, and after the test decides if the +revision (possibly with the needed tweaks) passed the test, rewind the +tree to the pristine state. Finally the "run" script can exit with +the status of the real test to let "git bisect run" command loop to +know the outcome. Author ------ diff --git a/git-bisect.sh b/git-bisect.sh index dbce0dfec9..3043f65514 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -1,14 +1,15 @@ #!/bin/sh -USAGE='[start|bad|good|next|reset|visualize|replay|log]' +USAGE='[start|bad|good|next|reset|visualize|replay|log|run]' LONG_USAGE='git bisect start [] reset bisect state and start bisection. git bisect bad [] mark a known-bad revision. git bisect good [...] mark ... known-good revisions. git bisect next find next bisection to test and check it out. git bisect reset [] finish bisection search and go back to branch. git bisect visualize show bisect status in gitk. -git bisect replay replay bisection log -git bisect log show bisect log.' +git bisect replay replay bisection log. +git bisect log show bisect log. +git bisect run ... use ... to automatically bisect.' . git-sh-setup require_work_tree @@ -185,6 +186,7 @@ bisect_reset() { rm -f "$GIT_DIR/refs/heads/bisect" "$GIT_DIR/head-name" rm -f "$GIT_DIR/BISECT_LOG" rm -f "$GIT_DIR/BISECT_NAMES" + rm -f "$GIT_DIR/BISECT_RUN" fi } @@ -220,6 +222,50 @@ bisect_replay () { bisect_auto_next } +bisect_run () { + while true + do + echo "running $@" + "$@" + res=$? + + # Check for really bad run error. + if [ $res -lt 0 -o $res -ge 128 ]; then + echo >&2 "bisect run failed:" + echo >&2 "exit code $res from '$@' is < 0 or >= 128" + exit $res + fi + + # Use "bisect_good" or "bisect_bad" + # depending on run success or failure. + if [ $res -gt 0 ]; then + next_bisect='bisect_bad' + else + next_bisect='bisect_good' + fi + + # We have to use a subshell because bisect_good or + # bisect_bad functions can exit. + ( $next_bisect > "$GIT_DIR/BISECT_RUN" ) + res=$? + + cat "$GIT_DIR/BISECT_RUN" + + if [ $res -ne 0 ]; then + echo >&2 "bisect run failed:" + echo >&2 "$next_bisect exited with error code $res" + exit $res + fi + + if grep "is first bad commit" "$GIT_DIR/BISECT_RUN" > /dev/null; then + echo "bisect run success" + exit 0; + fi + + done +} + + case "$#" in 0) usage ;; @@ -244,6 +290,8 @@ case "$#" in bisect_replay "$@" ;; log) cat "$GIT_DIR/BISECT_LOG" ;; + run) + bisect_run "$@" ;; *) usage ;; esac diff --git a/t/t6030-bisect-run.sh b/t/t6030-bisect-run.sh new file mode 100755 index 0000000000..39c72283b5 --- /dev/null +++ b/t/t6030-bisect-run.sh @@ -0,0 +1,57 @@ +#!/bin/sh +# +# Copyright (c) 2007 Christian Couder +# +test_description='Tests git-bisect run functionality' + +. ./test-lib.sh + +add_line_into_file() +{ + _line=$1 + _file=$2 + + if [ -f "$_file" ]; then + echo "$_line" >> $_file || return $? + MSG="Add <$_line> into <$_file>." + else + echo "$_line" > $_file || return $? + git add $_file || return $? + MSG="Create file <$_file> with <$_line> inside." + fi + + git-commit -m "$MSG" $_file +} + +HASH1= +HASH3= +HASH4= + +test_expect_success \ + 'set up basic repo with 1 file (hello) and 4 commits' \ + 'add_line_into_file "1: Hello World" hello && + add_line_into_file "2: A new day for git" hello && + add_line_into_file "3: Another new day for git" hello && + add_line_into_file "4: Ciao for now" hello && + HASH1=$(git rev-list HEAD | tail -1) && + HASH3=$(git rev-list HEAD | head -2 | tail -1) && + HASH4=$(git rev-list HEAD | head -1)' + +# We want to automatically find the commit that +# introduced "Another" into hello. +test_expect_success \ + 'git bisect run simple case' \ + 'echo "#!/bin/sh" > test_script.sh && + echo "grep Another hello > /dev/null" >> test_script.sh && + echo "test \$? -ne 0" >> test_script.sh && + chmod +x test_script.sh && + git bisect start && + git bisect good $HASH1 && + git bisect bad $HASH4 && + git bisect run ./test_script.sh > my_bisect_log.txt && + grep "$HASH3 is first bad commit" my_bisect_log.txt' + +# +# +test_done + From abba9dbbf450d4037a5e2054250f197169ac63eb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 23 Mar 2007 02:37:19 -0700 Subject: [PATCH 046/130] checkout: report where the new HEAD is upon detaching HEAD After "git reset" moves the HEAD around, it reports which commit you are on, which gives the user a warm fuzzy feeling of assurance. Give the same assurance from git-checkout when moving the detached HEAD around. Signed-off-by: Junio C Hamano --- git-checkout.sh | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/git-checkout.sh b/git-checkout.sh index 3c9b1bb05a..a7390e808c 100755 --- a/git-checkout.sh +++ b/git-checkout.sh @@ -163,6 +163,13 @@ cd_to_toplevel detached= detach_warn= +describe_detached_head () { + test -n "$quiet" || { + printf >&2 "$1 " + GIT_PAGER= git log >&2 -1 --pretty=oneline --abbrev-commit "$2" + } +} + if test -z "$branch$newbranch" && test "$new" != "$old" then detached="$new" @@ -173,9 +180,9 @@ If you want to create a new branch from this checkout, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b " fi -elif test -z "$oldbranch" && test -z "$quiet" +elif test -z "$oldbranch" then - echo >&2 "Previous HEAD position was $old" + describe_detached_head 'Previous HEAD position was' "$old" fi if [ "X$old" = X ] @@ -275,6 +282,7 @@ if [ "$?" -eq 0 ]; then then echo >&2 "$detach_warn" fi + describe_detached_head 'HEAD is now at' HEAD fi rm -f "$GIT_DIR/MERGE_HEAD" else From 673e58389fd8531ee1ac191350c2c10b1656486e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 23 Mar 2007 13:15:21 -0700 Subject: [PATCH 047/130] git-bisect: typofix The branch you are on while bisecting is always "bisect", and checking for "refs/heads/bisect*" is wrong. Only check if it is exactly "refs/heads/bisect". Signed-off-by: Junio C Hamano --- git-bisect.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-bisect.sh b/git-bisect.sh index 3043f65514..8eaea7cd19 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -50,7 +50,7 @@ bisect_start() { head=$(GIT_DIR="$GIT_DIR" git-symbolic-ref HEAD) || die "Bad HEAD - I need a symbolic ref" case "$head" in - refs/heads/bisect*) + refs/heads/bisect) if [ -s "$GIT_DIR/head-name" ]; then branch=`cat "$GIT_DIR/head-name"` else From 12cb8137332e21957195c3af2923c03a8aad5b5a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 23 Mar 2007 13:24:22 -0700 Subject: [PATCH 048/130] git-bisect.sh: properly dq $GIT_DIR Otherwise you would be in trouble if your GIT_DIR has IFS letters in it. Signed-off-by: Junio C Hamano --- git-bisect.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-bisect.sh b/git-bisect.sh index 8eaea7cd19..936b4a4b83 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -141,7 +141,7 @@ bisect_next() { bad=$(git-rev-parse --verify refs/bisect/bad) && good=$(git-rev-parse --sq --revs-only --not \ $(cd "$GIT_DIR" && ls refs/bisect/good-*)) && - rev=$(eval "git-rev-list --bisect $good $bad -- $(cat $GIT_DIR/BISECT_NAMES)") || exit + rev=$(eval "git-rev-list --bisect $good $bad -- $(cat "$GIT_DIR/BISECT_NAMES")") || exit if [ -z "$rev" ]; then echo "$bad was both good and bad" exit 1 From f9308a182e220c97cdbf90ee8de2ce21980cb7e9 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 23 Mar 2007 21:04:31 +0100 Subject: [PATCH 049/130] gitweb: Fix "next" link in commit view Fix copy'n'paste error in commit c9d193df which caused that "next" link for merge commits in "commit" view (merge: _commit_ _commit_ ...) was to "commitdiff" view instead of being to "commit" view. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 653ca3cc60..ea39d7e98b 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3719,7 +3719,7 @@ sub git_commit { $formats_nav .= '(merge: ' . join(' ', map { - $cgi->a({-href => href(action=>"commitdiff", + $cgi->a({-href => href(action=>"commit", hash=>$_)}, esc_html(substr($_, 0, 7))); } @$parents ) . From a4e9d71edb5f87b4dae57b8a474124451e397e6c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 23 Mar 2007 13:34:49 -0700 Subject: [PATCH 050/130] Fix path-limited "rev-list --bisect" termination condition. In a path-limited bisection, when the $bad commit is not changing the limited path, and the number of suspects is 1, the code miscounted and returned $bad from find_bisection(), which is not marked with TREECHANGE. This is of course filtered by the output routine, resulting in an empty output, in turn causing git-bisect driver to say "$bad was both good and bad". Illustration. Suppose you have these four commits, and only C changes path P. You know D is bad and A is good. A---B---C*--D git-bisect driver runs this to find a bisection point: $ git rev-list --bisect A..D -- P which calls find_bisection() with B, C and D. The set of commits that is given to this function is the same set of commits as rev-list without --bisect option and pathspec returns. Among them, only C is marked with TREECHANGE. Let's call the set of commits given to find_bisection() that are marked with TREECHANGE (or all of them if no path limiter is in effect) "the bisect set". In the above example, the size of the bisect set is 1 (contains only "C"). For each commit in its input, find_bisection() computes the number of commits it can reach in the bisect set. For a commit in the bisect set, this number includes itself, so the number is 1 or more. This number is called "depth", and computed by count_distance() function. When you have a bisect set of N commits, and a commit has depth D, how good is your bisection if you returned that commit? How good this bisection is can be measured by how many commits are effectively tested "together" by testing one commit. Currently you have (N-1) untested commits (the tip of the bisect set, although it is included in the bisect set, is already known to be bad). If the commit with depth D turns out to be bad, then your next bisect set will have D commits and you will have (D-1) untested commits left, which means you tested (N-1)-(D-1) = (N-D) commits with this bisection. If it turns out to be good, then your next bisect set will have (N-D) commits, and you will have (N-D-1) untested commits left, which means you tested (N-1)-(N-D-1) = D commits with this bisection. Therefore, the goodness of this bisection is is min(N-D, D), and find_bisection() function tries to find a commit that maximizes this, by initializing "closest" variable to 0 and whenever a commit with the goodness that is larger than the current "closest" is found, that commit and its goodness are remembered by updating "closest" variable. The "the commit with the best goodness so far" is kept in "best" variable, and is initialized to a commit that happens to be at the beginning of the list of commits given to this function (which may or may not be in the bisect set when path-limit is in use). However, when N is 1, then the sole tree-changing commit has depth of 1, and min(N-D, D) evaluates to 0. This is not larger than the initial value of "closest", and the "so far the best one" commit is never replaced in the loop. When path-limit is not in use, this is not a problem, as any commit in the input set is tree-changing. But when path-limit is in use, and when the starting "bad" commit does not change the specified path, it is not correct to return it. Signed-off-by: Junio C Hamano --- builtin-rev-list.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-rev-list.c b/builtin-rev-list.c index c2db5a5b03..51858e3233 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -180,7 +180,7 @@ static struct commit_list *find_bisection(struct commit_list *list) nr++; p = p->next; } - closest = 0; + closest = -1; best = list; for (p = list; p; p = p->next) { From 7891a2811dc7cae375e34c9f4fa6c8ecaef0f6d7 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 24 Mar 2007 06:29:58 +0100 Subject: [PATCH 051/130] Documentation: bisect: reformat some paragraphs. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index b7cd715380..a77fbe8484 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -122,17 +122,17 @@ like this: $ git bisect start arch/i386 include/asm-i386 ------------ -If you have a script that can tell if the current -source code is good or bad, you can automatically bisect using: +If you have a script that can tell if the current source code is good +or bad, you can automatically bisect using: ------------ $ git bisect run my_script ------------ -Note that the "run" script (`my_script` in the above example) -should exit with code 0 in -case the current source code is good and with a code between 1 and 127 -(included) in case the current source code is bad. +Note that the "run" script (`my_script` in the above example) should +exit with code 0 in case the current source code is good and with a +code between 1 and 127 (included) in case the current source code is +bad. Any other exit code (a program that does "exit(-1)" leaves $? = 255, see exit(3) manual page, the value is chopped with "& 0377") will From cc070d1f797c7488ed479817d893ad78fc4dae2b Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 24 Mar 2007 06:31:16 +0100 Subject: [PATCH 052/130] Documentation: bisect: reword one paragraph. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index a77fbe8484..4bd468e66d 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -134,9 +134,9 @@ exit with code 0 in case the current source code is good and with a code between 1 and 127 (included) in case the current source code is bad. -Any other exit code (a program that does "exit(-1)" leaves $? = 255, -see exit(3) manual page, the value is chopped with "& 0377") will -abort the automatic bisect process. +Any other exit code will abort the automatic bisect process. (A +program that does "exit(-1)" leaves $? = 255, see exit(3) manual page, +the value is chopped with "& 0377".) You may often find that during bisect you want to have near-constant tweaks (e.g., s/#define DEBUG 0/#define DEBUG 1/ in a header file, or From fed820ad5662d8b6f11b5e7f788fa87afe1ad919 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 24 Mar 2007 06:31:49 +0100 Subject: [PATCH 053/130] Documentation: bisect: reformat more paragraphs. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 73 +++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 4bd468e66d..0bfb1525b8 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -12,8 +12,8 @@ SYNOPSIS DESCRIPTION ----------- -The command takes various subcommands, and different options -depending on the subcommand: +The command takes various subcommands, and different options depending +on the subcommand: git bisect start [...] git bisect bad @@ -24,10 +24,9 @@ depending on the subcommand: git bisect log git bisect run ... -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 -object name. +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 object name. The way you use it is: @@ -38,15 +37,16 @@ $ 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 -bisect the revision tree and say something like: +When you give at least one bad and one good versions, it will bisect +the revision tree and say something like: ------------------------------------------------ Bisecting: 675 revisions left to test after this ------------------------------------------------ -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 +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 @@ -58,12 +58,12 @@ which will now say Bisecting: 337 revisions left to test after this ------------------------------------------------ -and you continue along, compiling that one, testing it, and depending on -whether it is good or bad, you say "git bisect good" or "git bisect bad", -and ask for the next bisection. +and you continue along, compiling that one, testing it, and depending +on whether it is good or bad, you say "git bisect good" or "git bisect +bad", and ask for the next bisection. -Until you have no more left, and you'll have been left with the first bad -kernel rev in "refs/bisect/bad". +Until you have no more left, and you'll have been left with the first +bad kernel rev in "refs/bisect/bad". Oh, and then after you want to reset to the original head, do a @@ -71,10 +71,10 @@ Oh, and then after you want to reset to the original head, do a $ git bisect reset ------------------------------------------------ -to get back to the master branch, instead of being in one of the bisection -branches ("git bisect start" will do that for you too, actually: it will -reset the bisection state, and before it does that it checks that you're -not using some old bisection branch). +to get back to the master branch, instead of being in one of the +bisection branches ("git bisect start" will do that for you too, +actually: it will reset the bisection state, and before it does that +it checks that you're not using some old bisection branch). During the bisection process, you can say @@ -84,9 +84,14 @@ $ git bisect visualize to see the currently remaining suspects in `gitk`. -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 +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 @@ -95,12 +100,13 @@ $ 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: +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. @@ -110,13 +116,12 @@ $ 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. +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: +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 From 1207f9e705bcd69af286b2f887e67ae2baad3faf Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 24 Mar 2007 06:30:33 +0100 Subject: [PATCH 054/130] Documentation: bisect: add some titles to some paragraphs. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 0bfb1525b8..8a42deb324 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -28,6 +28,9 @@ 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 object name. +Basic bisect commands: start, bad, good +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The way you use it is: ------------------------------------------------ @@ -65,6 +68,9 @@ bad", and ask for the next bisection. Until you have no more left, and you'll have been left with the first bad kernel rev in "refs/bisect/bad". +Bisect reset +~~~~~~~~~~~~ + Oh, and then after you want to reset to the original head, do a ------------------------------------------------ @@ -76,6 +82,9 @@ bisection branches ("git bisect start" will do that for you too, actually: it will reset the bisection state, and before it does that it checks that you're not using some old bisection branch). +Bisect visualize +~~~~~~~~~~~~~~~~ + During the bisection process, you can say ------------ @@ -84,6 +93,9 @@ $ git bisect visualize to see the currently remaining suspects in `gitk`. +Bisect log and bisect replay +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The good/bad input is logged, and ------------ @@ -100,6 +112,9 @@ $ git bisect replay that-file if you find later you made a mistake telling good/bad about a revision. +Avoiding to test a commit +~~~~~~~~~~~~~~~~~~~~~~~~~ + 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 @@ -119,6 +134,9 @@ $ git reset --hard HEAD~3 # try 3 revs before what Then compile and test the one you chose to try. After that, tell bisect what the result was as usual. +Cutting down bisection by giving path parameter to bisect start +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + 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: @@ -127,6 +145,9 @@ paths parameters when you say `bisect start`, like this: $ git bisect start arch/i386 include/asm-i386 ------------ +Bisect run +~~~~~~~~~~ + If you have a script that can tell if the current source code is good or bad, you can automatically bisect using: From 6cea055547c6f90450a34a5f30db4a48e154ab81 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sat, 24 Mar 2007 06:32:05 +0100 Subject: [PATCH 055/130] Documentation: bisect: make a comment fit better in the man page. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- Documentation/git-bisect.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/git-bisect.txt b/Documentation/git-bisect.txt index 8a42deb324..b2bc58d851 100644 --- a/Documentation/git-bisect.txt +++ b/Documentation/git-bisect.txt @@ -35,9 +35,9 @@ 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 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 bisect From e43b01058222da3fa0ba9b662f6621709a5981b3 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 23 Mar 2007 17:06:11 +0100 Subject: [PATCH 056/130] git-revert: Revert revert message to old behaviour When converting from the shell script, based on a misreading of the sed invocation, the builtin included the abbreviated commit name, and did _not_ include the quotes around the oneline message. This fixes it. [jc: with a fix for the typo/thinko spotted by Linus, and also removing the unwanted abbrev at the beginning.] Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- builtin-revert.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/builtin-revert.c b/builtin-revert.c index f3f3f5c6ee..4ba0ee63ab 100644 --- a/builtin-revert.c +++ b/builtin-revert.c @@ -294,13 +294,13 @@ static int revert_or_cherry_pick(int argc, const char **argv) oneline = get_oneline(message); if (action == REVERT) { + char *oneline_body = strchr(oneline, ' '); + base = commit; next = commit->parents->item; - add_to_msg("Revert "); - add_to_msg(find_unique_abbrev(commit->object.sha1, - DEFAULT_ABBREV)); - add_to_msg(oneline); - add_to_msg("\nThis reverts commit "); + add_to_msg("Revert \""); + add_to_msg(oneline_body + 1); + add_to_msg("\"\n\nThis reverts commit "); add_to_msg(sha1_to_hex(commit->object.sha1)); add_to_msg(".\n"); } else { From 2499857b0b5c1801da659e8bff976c1e038f3f3f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 24 Mar 2007 03:08:54 -0700 Subject: [PATCH 057/130] git-am documentation: describe what is taken from where. Signed-off-by: Junio C Hamano --- Documentation/git-am.txt | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt index 13a7389867..148ce40568 100644 --- a/Documentation/git-am.txt +++ b/Documentation/git-am.txt @@ -87,6 +87,33 @@ default. You could use `--no-utf8` to override this. DISCUSSION ---------- +The commit author name is taken from the "From: " line of the +message, and commit author time is taken from the "Date: " line +of the message. The "Subject: " line is used as the title of +the commit, after stripping common prefix "[PATCH ]". +It is supposed to describe what the commit is about concisely as +a one line text. + +The body of the message (iow, after a blank line that terminates +RFC2822 headers) can begin with "Subject: " and "From: " lines +that are different from those of the mail header, to override +the values of these fields. + +The commit message is formed by the title taken from the +"Subject: ", a blank line and the body of the message up to +where the patch begins. Excess whitespaces at the end of the +lines are automatically stripped. + +The patch is expected to be inline, directly following the +message. Any line that is of form: + +* three-dashes and end-of-line, or +* a line that begins with "diff -", or +* a line that begins with "Index: " + +is taken as the beginning of a patch, and the commit log message +is terminated before the first occurrence of such a line. + When initially invoking it, you give it names of the mailboxes to crunch. Upon seeing the first patch that does not apply, it aborts in the middle, just like 'git-applymbox' does. You can From 290b1467a387a3e5306028f36118a52958fa36c5 Mon Sep 17 00:00:00 2001 From: Li Yang Date: Tue, 6 Mar 2007 11:58:56 +0800 Subject: [PATCH 058/130] gitweb: Change to use explicitly function call cgi->escapHTML() Change to use explicitly function call cgi->escapHTML(). This fix the problem on some systems that escapeHTML() is not functioning, as default CGI is not setting 'escape' parameter. Signed-off-by: Li Yang Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index ea39d7e98b..775eebe0f3 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -591,7 +591,7 @@ sub esc_html ($;%) { my %opts = @_; $str = to_utf8($str); - $str = escapeHTML($str); + $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; } @@ -605,7 +605,7 @@ sub esc_path { my %opts = @_; $str = to_utf8($str); - $str = escapeHTML($str); + $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; } From 346d5e1835937d701785300717ce34f92609c2b3 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Wed, 7 Mar 2007 02:21:25 +0100 Subject: [PATCH 059/130] gitweb: Don't escape attributes in CGI.pm HTML methods There is no need to escape HTML tag's attributes in CGI.pm HTML methods (like CGI::a()), because CGI.pm does attribute escaping automatically. $cgi->a({ ... -attribute => atribute_value }, tag_contents) is translated to tag_contents The rules for escaping attribute values (which are string contents) are different. For example you have to take care about escaping embedded '"' and "'" characters; CGI::a() does that for us automatically. CGI::a() does not HTML escape tag_contents; we would need to write some bold text for example. So we use esc_html (or esc_path) to escape tag_contents as needed. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 775eebe0f3..5214050a88 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -1974,17 +1974,17 @@ sub git_print_page_path { $fullname .= ($fullname ? '/' : '') . $dir; print $cgi->a({-href => href(action=>"tree", file_name=>$fullname, hash_base=>$hb), - -title => esc_html($fullname)}, esc_path($dir)); + -title => $fullname}, esc_path($dir)); print " / "; } if (defined $type && $type eq 'blob') { print $cgi->a({-href => href(action=>"blob_plain", file_name=>$file_name, hash_base=>$hb), - -title => esc_html($name)}, esc_path($basename)); + -title => $name}, esc_path($basename)); } elsif (defined $type && $type eq 'tree') { print $cgi->a({-href => href(action=>"tree", file_name=>$file_name, hash_base=>$hb), - -title => esc_html($name)}, esc_path($basename)); + -title => $name}, esc_path($basename)); print " / "; } else { print esc_path($basename); From 4ae89b76252d1c13a6675a2a4e491983946d72ec Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 24 Mar 2007 20:59:13 +0100 Subject: [PATCH 060/130] gitweb: Fix not marking signoff lines in "log" view The CSS selector for signoff lines style was too strict: in the "log" view the commit message is not encompassed in container "page_body" div. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitweb/gitweb.css b/gitweb/gitweb.css index 7177c6e86b..5e40292404 100644 --- a/gitweb/gitweb.css +++ b/gitweb/gitweb.css @@ -107,7 +107,7 @@ span.age { font-style: italic; } -div.page_body span.signoff { +span.signoff { color: #888888; } From cd67c8e0bc6f61ffccc12d1775bc1a200df5fe85 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 24 Mar 2007 20:59:53 +0100 Subject: [PATCH 061/130] gitweb: Add some installation notes in gitweb/INSTALL Add some installation and configuration notes for gitweb in gitweb/INSTALL. Make use of filling gitweb configuration by Makefile. It does not cover (yet?) all the configuration variables and options. Some of contents duplicates information in gitweb/README file (it is referred from gitweb/INSTALL). Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/INSTALL | 184 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 gitweb/INSTALL diff --git a/gitweb/INSTALL b/gitweb/INSTALL new file mode 100644 index 0000000000..371407dc23 --- /dev/null +++ b/gitweb/INSTALL @@ -0,0 +1,184 @@ +GIT web Interface (gitweb) Installation +======================================= + +First you have to generate gitweb.cgi from gitweb.perl using +"make gitweb/gitweb.cgi", then copy appropriate files (gitweb.cgi, +gitweb.css, git-logo.png and git-favicon.png) to their destination. +For example if git was (or is) installed with /usr prefix, you can do + + $ make prefix=/usr gitweb/gitweb.cgi ;# as yourself + # cp gitweb/git* /var/www/cgi-bin/ ;# as root + +Alternatively you can use autoconf generated ./configure script to +set up path to git binaries (via config.mak.autogen), so you can write +instead + + $ make configure ;# as yourself + $ ./configure --prefix=/usr ;# as yourself + $ make gitweb/gitweb.cgi ;# as yourself + # cp gitweb/git* /var/www/cgi-bin/ ;# as root + +The above example assumes that your web server is configured to run +[executable] files in /var/www/cgi-bin/ as server scripts (as CGI +scripts). + + +Build time configuration +------------------------ + +See also "How to configure gitweb for your local system" in README +file for gitweb (in gitweb/README). + +- There are many configuration variables which affects building of + gitweb.cgi; see "default configuration for gitweb" section in main + (top dir) Makefile, and instructions for building gitweb/gitweb.cgi + target. + + One of most important is where to find git wrapper binary. Gitweb + tries to find git wrapper at $(bindir)/git, so you have to set $bindir + when building gitweb.cgi, or $prefix from which $bindir is derived. If + you build and install gitweb together with the rest of git suite, + there should be no problems. Otherwise, if git was for example + installed from a binary package, you have to set $prefix (or $bindir) + accordingly. + +- Another important issue is where are git repositories you want to make + available to gitweb. By default gitweb search for repositories under + /pub/git; if you want to have projects somewhere else, like /home/git, + use GITWEB_PROJECTROOT build configuration variable. + + By default all git repositories under projectroot are visible and + available to gitweb. List of projects is generated by default by + scanning the projectroot directory for git repositories. This can be + changed (configured) as described in "Gitweb repositories" section + below. + + Note that gitweb deals directly with object database, and does not + need working directory; the name of the project is the name of its + repository object database, usually projectname.git for bare + repositories. If you want to provide gitweb access to non-bare (live) + repository, you can make projectname.git symbolic link under + projectroot linking to projectname/.git (but it is just + a suggestion). + +- You can control where gitweb tries to find its main CSS style file, + its favicon and logo with GITWEB_CSS, GITWEB_FAVICON and GITWEB_LOGO + build configuration variables. By default gitweb tries to find them + in the same directory as gitweb.cgi script. + +Build example +~~~~~~~~~~~~~ + +- To install gitweb to /var/www/cgi-bin/gitweb/ when git wrapper + is installed at /usr/local/bin/git and the repositories (projects) + we want to display are under /home/local/scm, you can do + + make GITWEB_PROJECTROOT="/home/local/scm" \ + GITWEB_CSS="/gitweb/gitweb.css" \ + GITWEB_LOGO="/gitweb/git-logo.png" \ + GITWEB_FAVICON="/gitweb/git-favicon.png" \ + bindir=/usr/local/bin \ + gitweb/gitweb.cgi + + cp -fv ~/git/gitweb/gitweb.{cgi,css} \ + ~/git/gitweb/git-{favicon,logo}.png \ + /var/www/cgi-bin/gitweb/ + + +Gitweb config file +------------------ + +See also "Runtime gitweb configuration" section in README file +for gitweb (in gitweb/README). + +- You can configure gitweb further using gitweb configuration file; + by default it is file named gitweb_config.perl in the same place as + gitweb.cgi script. You can control default place for config file + using GITWEB_CONFIG build configuration variable, and you can set it + using GITWEB_CONFIG environmental variable. + +- Gitweb config file is [fragment] of perl code. You can set variables + using "our $variable = value"; text from "#" character until the end + of a line is ignored. See perlsyn(1) for details. + + See the top of gitweb.perl file for examples of customizable options. + + +Gitweb repositories: +-------------------- + +- By default all git repositories under projectroot are visible and + available to gitweb. List of projects is generated by default by + scanning the projectroot directory for git repositories (for object + databases to be more exact). + + You can provide pre-generated list of [visible] repositories, + together with information about their owners (the project ownership + is taken from owner of repository directory otherwise), by setting + GITWEB_LIST build configuration variable (or $projects_list variable + in gitweb config file) to point to a plain file. + + Each line of projects list file should consist of url-encoded path + to project repository database (relative to projectroot) separated + by space from url-encoded project owner; spaces in both project path + and project owner have to be encoded as either '%20' or '+'. + + You can generate projects list index file using project_index action + (the 'TXT' link on projects list page) directly from gitweb. + +- By default even if project is not visible on projects list page, you + can view it nevertheless by hand-crafting gitweb URL. You can set + GITWEB_STRICT_EXPORT build configuration variable (or $strict_export + variable in gitweb config file) to only allow viewing of + repositories also shown on the overview page. + +- Alternatively, you can configure gitweb to only list and allow + viewing of the explicitly exported repositories, via + GITWEB_EXPORT_OK build configuration variable (or $export_ok + variable in gitweb config file). If it evaluates to true, gitweb + show repository only if this file exists in its object database + (if directory has the magic file $export_ok). + + +Requirements +------------ + + - Core git tools + - Perl + - Perl modules: CGI, Encode, Fcntl, File::Find, File::Basename. + - web server + + +Example web server configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +See also "Webserver configuration" section in README file for gitweb +(in gitweb/README). + + +- Apache2, gitweb installed as CGI script, + under /var/www/cgi-bin/ + + ScriptAlias /cgi-bin/ "/var/www/cgi-bin/" + + + Options Indexes FollowSymlinks ExecCGI + AllowOverride None + Order allow,deny + Allow from all + + +- Apache2, gitweb installed as mod_perl legacy script, + under /var/www/perl/ + + Alias /perl "/var/www/perl" + + + SetHandler perl-script + PerlResponseHandler ModPerl::Registry + PerlOptions +ParseHeaders + Options Indexes FollowSymlinks +ExecCGI + AllowOverride None + Order allow,deny + Allow from all + From 46d409d0bf25b361f812eec4888c46509c203a6d Mon Sep 17 00:00:00 2001 From: Andy Parkins Date: Fri, 23 Mar 2007 10:21:59 +0000 Subject: [PATCH 062/130] update-hook: remove e-mail sending hook. The update hook's only job is to decide is a particular update is allowed or not. It was not the right place to send out update notification e-mails from to begin with, as the final stage of updating refs can fail after this hook runs. Signed-off-by: Andy Parkins Signed-off-by: Junio C Hamano --- templates/hooks--update | 225 +--------------------------------------- 1 file changed, 3 insertions(+), 222 deletions(-) diff --git a/templates/hooks--update b/templates/hooks--update index 1a60773890..0ff03309e6 100644 --- a/templates/hooks--update +++ b/templates/hooks--update @@ -1,36 +1,16 @@ #!/bin/sh # -# An example hook script to mail out commit update information. -# It can also blocks tags that aren't annotated. +# An example hook script to blocks unannotated tags from entering. # Called by git-receive-pack with arguments: refname sha1-old sha1-new # # To enable this hook, make this file executable by "chmod +x update". # # Config # ------ -# hooks.mailinglist -# This is the list that all pushes will go to; leave it blank to not send -# emails frequently. The log email will list every log entry in full between -# the old ref value and the new ref value. -# hooks.announcelist -# This is the list that all pushes of annotated tags will go to. Leave it -# blank to just use the mailinglist field. The announce emails list the -# short log summary of the changes since the last annotated tag # hooks.allowunannotated # This boolean sets whether unannotated tags will be allowed into the # repository. By default they won't be. # -# Notes -# ----- -# All emails have their subjects prefixed with "[SCM]" to aid filtering. -# All emails include the headers "X-Git-Refname", "X-Git-Oldrev", -# "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and info. - -# --- Constants -EMAILPREFIX="[SCM] " -LOGBEGIN="- Log -----------------------------------------------------------------" -LOGEND="-----------------------------------------------------------------------" -DATEFORMAT="%F %R %z" # --- Command line refname="$1" @@ -51,9 +31,6 @@ if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then fi # --- Config -projectdesc=$(cat $GIT_DIR/description) -recipients=$(git-repo-config hooks.mailinglist) -announcerecipients=$(git-repo-config hooks.announcelist) allowunannotated=$(git-repo-config --bool hooks.allowunannotated) # check for no description @@ -68,224 +45,28 @@ newrev_type=$(git-cat-file -t $newrev) case "$refname","$newrev_type" in refs/tags/*,commit) # un-annotated tag - refname_type="tag" short_refname=${refname##refs/tags/} if [ "$allowunannotated" != "true" ]; then - echo "*** The un-annotated tag, $short_refname is not allowed in this repository" >&2 + echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2 echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2 exit 1 fi ;; refs/tags/*,tag) # annotated tag - refname_type="annotated tag" - short_refname=${refname##refs/tags/} - # change recipients - if [ -n "$announcerecipients" ]; then - recipients="$announcerecipients" - fi ;; refs/heads/*,commit) # branch - refname_type="branch" - short_refname=${refname##refs/heads/} ;; refs/remotes/*,commit) # tracking branch - refname_type="tracking branch" - short_refname=${refname##refs/remotes/} - # Should this even be allowed? - echo "*** Push-update of tracking branch, $refname. No email generated." >&2 - exit 0 ;; *) # Anything else (is there anything else?) - echo "*** Update hook: unknown type of update, \"$newrev_type\", to ref $refname" >&2 + echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2 exit 1 ;; esac -# Check if we've got anyone to send to -if [ -z "$recipients" ]; then - # If the email isn't sent, then at least give the user some idea of what command - # would generate the email at a later date - echo "*** No recipients found - no email will be sent, but the push will continue" >&2 - echo "*** for $0 $1 $2 $3" >&2 - exit 0 -fi - -# --- Email parameters -committer=$(git show --pretty=full -s $newrev | grep "^Commit: " | sed -e "s/^Commit: //") -describe=$(git describe $newrev 2>/dev/null) -if [ -z "$describe" ]; then - describe=$newrev -fi - -# --- Email (all stdout will be the email) -( -# Generate header -cat <<-EOF -From: $committer -To: $recipients -Subject: ${EMAILPREFIX}$projectdesc $refname_type, $short_refname now at $describe -X-Git-Refname: $refname -X-Git-Reftype: $refname_type -X-Git-Oldrev: $oldrev -X-Git-Newrev: $newrev - -Hello, - -This is an automated email from the git hooks/update script, it was -generated because a ref change was pushed to the repository. - -Updating $refname_type, $short_refname, -EOF - -case "$refname_type" in - "tracking branch"|branch) - if expr "$oldrev" : '0*$' >/dev/null - then - # If the old reference is "0000..0000" then this is a new branch - # and so oldrev is not valid - echo " as a new $refname_type" - echo " to $newrev ($newrev_type)" - echo "" - echo $LOGBEGIN - # This shows all log entries that are not already covered by - # another ref - i.e. commits that are now accessible from this - # ref that were previously not accessible - git log $newrev --not --all - echo $LOGEND - else - # oldrev is valid - oldrev_type=$(git-cat-file -t "$oldrev") - - # Now the problem is for cases like this: - # * --- * --- * --- * (oldrev) - # \ - # * --- * --- * (newrev) - # i.e. there is no guarantee that newrev is a strict subset - # of oldrev - (would have required a force, but that's allowed). - # So, we can't simply say rev-list $oldrev..$newrev. Instead - # we find the common base of the two revs and list from there - baserev=$(git-merge-base $oldrev $newrev) - - # Commit with a parent - for rev in $(git-rev-list $newrev --not $baserev --all) - do - revtype=$(git-cat-file -t "$rev") - echo " via $rev ($revtype)" - done - if [ "$baserev" = "$oldrev" ]; then - echo " from $oldrev ($oldrev_type)" - else - echo " based on $baserev" - echo " from $oldrev ($oldrev_type)" - echo "" - echo "This ref update crossed a branch point; i.e. the old rev is not a strict subset" - echo "of the new rev. This occurs, when you --force push a change in a situation" - echo "like this:" - echo "" - echo " * -- * -- B -- O -- O -- O ($oldrev)" - echo " \\" - echo " N -- N -- N ($newrev)" - echo "" - echo "Therefore, we assume that you've already had alert emails for all of the O" - echo "revisions, and now give you all the revisions in the N branch from the common" - echo "base, B ($baserev), up to the new revision." - fi - echo "" - echo $LOGBEGIN - git log $newrev --not $baserev --all - echo $LOGEND - echo "" - echo "Diffstat:" - git-diff-tree --no-color --stat -M -C --find-copies-harder $baserev..$newrev - fi - ;; - "annotated tag") - # Should we allow changes to annotated tags? - if expr "$oldrev" : '0*$' >/dev/null - then - # If the old reference is "0000..0000" then this is a new atag - # and so oldrev is not valid - echo " to $newrev ($newrev_type)" - else - echo " to $newrev ($newrev_type)" - echo " from $oldrev" - fi - - # If this tag succeeds another, then show which tag it replaces - prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null) - if [ -n "$prevtag" ]; then - echo " replaces $prevtag" - fi - - # Read the tag details - eval $(git cat-file tag $newrev | \ - sed -n '4s/tagger \([^>]*>\)[^0-9]*\([0-9]*\).*/tagger="\1" ts="\2"/p') - tagged=$(date --date="1970-01-01 00:00:00 +0000 $ts seconds" +"$DATEFORMAT") - - echo " tagged by $tagger" - echo " on $tagged" - - echo "" - echo $LOGBEGIN - echo "" - - if [ -n "$prevtag" ]; then - git rev-list --pretty=short "$prevtag..$newrev" | git shortlog - else - git rev-list --pretty=short $newrev | git shortlog - fi - - echo $LOGEND - echo "" - ;; - *) - # By default, unannotated tags aren't allowed in; if - # they are though, it's debatable whether we would even want an - # email to be generated; however, I don't want to add another config - # option just for that. - # - # Unannotated tags are more about marking a point than releasing - # a version; therefore we don't do the shortlog summary that we - # do for annotated tags above - we simply show that the point has - # been marked, and print the log message for the marked point for - # reference purposes - # - # Note this section also catches any other reference type (although - # there aren't any) and deals with them in the same way. - if expr "$oldrev" : '0*$' >/dev/null - then - # If the old reference is "0000..0000" then this is a new tag - # and so oldrev is not valid - echo " as a new $refname_type" - echo " to $newrev ($newrev_type)" - else - echo " to $newrev ($newrev_type)" - echo " from $oldrev" - fi - echo "" - echo $LOGBEGIN - git-show --no-color --root -s $newrev - echo $LOGEND - echo "" - ;; -esac - -# Footer -cat <<-EOF - -hooks/update ---- -Git Source Code Management System -$0 $1 \\ - $2 \\ - $3 -EOF -#) | cat >&2 -) | /usr/sbin/sendmail -t - # --- Finished exit 0 From 0e55181f29ee6599ab6888ac54d186c83d355a70 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 24 Mar 2007 11:58:22 -0400 Subject: [PATCH 063/130] make it more obvious that temporary files are temporary files When some operations are interrupted (or "die()'d" or crashed) then the partial object/pack/index file may remain around. Make it more obvious in their name that those files are temporary stuff and can be cleaned up if no operation is in progress. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- fast-import.c | 4 ++-- index-pack.c | 4 ++-- sha1_file.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fast-import.c b/fast-import.c index 55ffae4fa6..bea12151c2 100644 --- a/fast-import.c +++ b/fast-import.c @@ -630,7 +630,7 @@ static void start_packfile(void) int pack_fd; snprintf(tmpfile, sizeof(tmpfile), - "%s/pack_XXXXXX", get_object_directory()); + "%s/tmp_pack_XXXXXX", get_object_directory()); pack_fd = mkstemp(tmpfile); if (pack_fd < 0) die("Can't create %s: %s", tmpfile, strerror(errno)); @@ -730,7 +730,7 @@ static char *create_index(void) } snprintf(tmpfile, sizeof(tmpfile), - "%s/index_XXXXXX", get_object_directory()); + "%s/tmp_idx_XXXXXX", get_object_directory()); idx_fd = mkstemp(tmpfile); if (idx_fd < 0) die("Can't create %s: %s", tmpfile, strerror(errno)); diff --git a/index-pack.c b/index-pack.c index 61eb20e45b..6284fe3760 100644 --- a/index-pack.c +++ b/index-pack.c @@ -139,7 +139,7 @@ static const char *open_pack_file(const char *pack_name) if (!pack_name) { static char tmpfile[PATH_MAX]; snprintf(tmpfile, sizeof(tmpfile), - "%s/pack_XXXXXX", get_object_directory()); + "%s/tmp_pack_XXXXXX", get_object_directory()); output_fd = mkstemp(tmpfile); pack_name = xstrdup(tmpfile); } else @@ -690,7 +690,7 @@ static const char *write_index_file(const char *index_name, unsigned char *sha1) if (!index_name) { static char tmpfile[PATH_MAX]; snprintf(tmpfile, sizeof(tmpfile), - "%s/index_XXXXXX", get_object_directory()); + "%s/tmp_idx_XXXXXX", get_object_directory()); fd = mkstemp(tmpfile); index_name = xstrdup(tmpfile); } else { diff --git a/sha1_file.c b/sha1_file.c index 940bab5612..e412c70f27 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1979,7 +1979,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha return error("sha1 file %s: %s\n", filename, strerror(errno)); } - snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); + snprintf(tmpfile, sizeof(tmpfile), "%s/tmp_obj_XXXXXX", get_object_directory()); fd = mkstemp(tmpfile); if (fd < 0) { @@ -2105,7 +2105,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, int ret; SHA_CTX c; - snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory()); + snprintf(tmpfile, sizeof(tmpfile), "%s/tmp_obj_XXXXXX", get_object_directory()); local = mkstemp(tmpfile); if (local < 0) { From b5b8d8141af7d854cf481a640d07aed7bddfaaaa Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 24 Mar 2007 12:02:27 -0400 Subject: [PATCH 064/130] write_sha1_from_fd() should make new objects read-only ... like it is done everywhere else. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- sha1_file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sha1_file.c b/sha1_file.c index e412c70f27..0897b945e5 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2154,6 +2154,7 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, } while (1); inflateEnd(&stream); + fchmod(local, 0444); close(local); SHA1_Final(real_sha1, &c); if (ret != Z_STREAM_END) { From 2a18c266d04273be05ed29c589a5c29b8e68134d Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Sun, 25 Mar 2007 01:55:43 +0100 Subject: [PATCH 065/130] Document --quiet option to git-diff Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- Documentation/diff-options.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt index 77a3f78dd7..1689c74817 100644 --- a/Documentation/diff-options.txt +++ b/Documentation/diff-options.txt @@ -164,5 +164,8 @@ That is, it exits with 1 if there were differences and 0 means no differences. +--quiet:: + Disable all output of the program. Implies --exit-code. + For more detailed explanation on these common options, see also link:diffcore.html[diffcore documentation]. From 06aff47b225506c4603a6f5ec5b4b16aa6a9d7ba Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Sun, 25 Mar 2007 01:56:13 +0100 Subject: [PATCH 066/130] Use diff* with --exit-code in git-am, git-rebase and git-merge-ours This simplifies the shell code, reduces its memory footprint, and speeds things up. The performance improvements should be noticable when git-rebase works on big commits. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- git-am.sh | 18 +++++++----------- git-merge-ours.sh | 2 +- git-rebase.sh | 10 ++++------ 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/git-am.sh b/git-am.sh index 88af8dd256..e69ecbfdb1 100755 --- a/git-am.sh +++ b/git-am.sh @@ -408,12 +408,10 @@ do # trust what the user has in the index file and the # working tree. resolved= - changed="$(git-diff-index --cached --name-only HEAD)" - if test '' = "$changed" - then + git-diff-index --quiet --cached HEAD && { echo "No changes - did you forget to use 'git add'?" stop_here_user_resolve $this - fi + } unmerged=$(git-ls-files -u) if test -n "$unmerged" then @@ -435,13 +433,11 @@ do then # Applying the patch to an earlier tree and merging the # result may have produced the same tree as ours. - changed="$(git-diff-index --cached --name-only HEAD)" - if test '' = "$changed" - then - echo No changes -- Patch already applied. - go_next - continue - fi + git-diff-index --quiet --cached HEAD && { + echo No changes -- Patch already applied. + go_next + continue + } # clear apply_status -- we have successfully merged. apply_status=0 fi diff --git a/git-merge-ours.sh b/git-merge-ours.sh index 4f3d053889..2b6a5c0d10 100755 --- a/git-merge-ours.sh +++ b/git-merge-ours.sh @@ -9,6 +9,6 @@ # because the current index is what we will be committing as the # merge result. -test "$(git-diff-index --cached --name-status HEAD)" = "" || exit 2 +git-diff-index --quiet --cached HEAD || exit 2 exit 0 diff --git a/git-rebase.sh b/git-rebase.sh index aadd580f8d..1d96f32685 100755 --- a/git-rebase.sh +++ b/git-rebase.sh @@ -59,7 +59,7 @@ continue_merge () { die "$RESOLVEMSG" fi - if test -n "`git-diff-index HEAD`" + if ! git-diff-index --quiet HEAD then if ! git-commit -C "`cat $dotest/current`" then @@ -124,13 +124,11 @@ while case "$#" in 0) break ;; esac do case "$1" in --continue) - diff=$(git-diff-files) - case "$diff" in - ?*) echo "You must edit all merge conflicts and then" + git-diff-files --quiet || { + echo "You must edit all merge conflicts and then" echo "mark them as resolved using git update-index" exit 1 - ;; - esac + } if test -d "$dotest" then prev_head="`cat $dotest/prev_head`" From 620d3f4216e5a9cf29f1de8c91ea5380e766238c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 25 Mar 2007 17:42:32 -0700 Subject: [PATCH 067/130] Update README to point at a few key periodical messages to the list They give a good starting point to new people who want to get involved. This owes suggestions by Martin Langhoff and Steven Grimm. Signed-off-by: Junio C Hamano --- README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README b/README index 441167cb8a..548142c327 100644 --- a/README +++ b/README @@ -38,3 +38,9 @@ requests, comments and patches to git@vger.kernel.org. To subscribe to the list, send an email with just "subscribe git" in the body to majordomo@vger.kernel.org. The mailing list archives are available at http://marc.theaimsgroup.com/?l=git and other archival sites. + +The messages titled "A note from the maintainer", "What's in +git.git (stable)" and "What's cooking in git.git (topics)" and +the discussion following them on the mailing list give a good +reference for project status, development direction and +remaining tasks. From 3301521a2584128c23cae14bebbe260326dbcedf Mon Sep 17 00:00:00 2001 From: James Bowes Date: Sun, 25 Mar 2007 20:39:36 -0400 Subject: [PATCH 068/130] use xmalloc in git.c and help.c Signed-off-by: James Bowes Signed-off-by: Junio C Hamano --- git.c | 2 +- help.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/git.c b/git.c index ed1c65e309..5b1bc2a895 100644 --- a/git.c +++ b/git.c @@ -99,7 +99,7 @@ static int split_cmdline(char *cmdline, const char ***argv) int src, dst, count = 0, size = 16; char quoted = 0; - *argv = malloc(sizeof(char*) * size); + *argv = xmalloc(sizeof(char*) * size); /* split alias_string */ (*argv)[count++] = cmdline; diff --git a/help.c b/help.c index 0893fea025..be8651a739 100644 --- a/help.c +++ b/help.c @@ -58,7 +58,7 @@ static void add_cmdname(const char *name, int len) if (!cmdname) oom(); } - ent = malloc(sizeof(*ent) + len); + ent = xmalloc(sizeof(*ent) + len); if (!ent) oom(); ent->len = len; From 0b59451c1be6be3d0df80be9dc8aeedb355ca44b Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 25 Mar 2007 16:35:31 -0700 Subject: [PATCH 069/130] git-svn: fix rel_path() when not connected to the repository root This should fix fetching for people who did not use "git svn --minimize" or cannot connect to the repository root due to the lack of permissions. I'm not sure what I was on when I made the change to the rel_path() function in 4e9f6cc78e5d955bd0faffe76ae9aea6590189f1 that made it die() when we weren't connected to the repository root :x Thanks to Sven Verdoolaege for reporting this bug. Signed-off-by: Junio C Hamano --- git-svn.perl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index e8457893db..e0a48c2a8b 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -1327,8 +1327,10 @@ sub rel_path { my ($self) = @_; my $repos_root = $self->ra->{repos_root}; return $self->{path} if ($self->{url} eq $repos_root); - die "BUG: rel_path failed! repos_root: $repos_root, Ra URL: ", - $self->ra->{url}, " path: $self->{path}, URL: $self->{url}\n"; + my $url = $self->{url} . + (length $self->{path} ? "/$self->{path}" : $self->{path}); + $url =~ s!^\Q$repos_root\E(?:/+|$)!!g; + $url; } sub traverse_ignore { From b6da18b1d103617a5944d470a1f17e398f8141e4 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 25 Mar 2007 18:00:45 -0700 Subject: [PATCH 070/130] GIT 1.5.1-rc2 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.1.txt | 53 ++++++++++++++++++++++++-------- GIT-VERSION-GEN | 2 +- 2 files changed, 41 insertions(+), 14 deletions(-) diff --git a/Documentation/RelNotes-1.5.1.txt b/Documentation/RelNotes-1.5.1.txt index f78cf56bc8..8461fb4371 100644 --- a/Documentation/RelNotes-1.5.1.txt +++ b/Documentation/RelNotes-1.5.1.txt @@ -10,11 +10,15 @@ Updates since v1.5.0 * New commands and options. - - "git log" and friends take --reverse. This makes output - that typically goes reverse order in chronological order. - "git shortlog" usually lists commits in chronological order, - but with "--reverse", they are shown in reverse - chronological order. + - "git log" and friends take --reverse, which instructs them + to give their output in the order opposite from their usual. + They typically output from new to old, but with this option + their output would read from old to new. "git shortlog" + usually lists older commits first, but with this option, + they are shown from new to old. + + - "git log --pretty=format:" to allow more flexible + custom log output. - "git diff" learned --ignore-space-at-eol. This is a weaker form of --ignore-space-change. @@ -22,9 +26,6 @@ Updates since v1.5.0 - "git diff --no-index pathA pathB" can be used as diff replacement with git specific enhancements. - - "git diff --pretty=format:" to allow more flexible - custom log output. - - "git diff --no-index" can read from '-' (standard input). - "git diff" also learned --exit-code to exit with non-zero @@ -33,6 +34,17 @@ Updates since v1.5.0 backward incompatible change; it will stay as an option for now. + - "git diff --quiet" is --exit-code with output turned off, + meant for scripted use to quickly determine if there is any + tree-level difference. + + - Textual patch generation with "git diff" without -w/-b + option has been significantly optimized. "git blame" got + faster because of the same change. + + - "git log" and "git rev-list" has been optimized + significantly when they are used with pathspecs. + - "git branch --track" can be used to set up configuration variables to help it easier to base your work on branches you track from a remote site. @@ -61,6 +73,19 @@ Updates since v1.5.0 symlinks on filesystems that do not support them; they are checked out as regular files instead. + - You can name a commit object with its first line of the + message. The syntax to use is ':/message text'. E.g. + + $ git show ":/object name: introduce ':/' notation" + + means the same thing as: + + $ git show 28a4d940443806412effa246ecc7768a21553ec7 + + - "git bisect" learned a new command "run" that takes a script + to run after each revision is checked out to determine if it + is good or bad, to automate the bisection process. + * Updated behaviour of existing commands. @@ -133,6 +158,9 @@ Updates since v1.5.0 - send-email learned configurable bcc and chain-reply-to. + - "git remote show $remote" also talks about branches that + would be pushed if you run "git push remote". + - Using objects from packs is now seriouly optimized by clever use of a cache. This should be most noticeable in git-log family of commands that involve reading many tree objects. @@ -143,10 +171,9 @@ Updates since v1.5.0 * Hooks - - The sample update hook to show how to send out notification - e-mail was updated to show only new commits that appeared in - the repository. Earlier, it showed new commits that appeared - on the branch. + - The part to send out notification e-mails was removed from + the sample update hook, as it was not an appropriate place + to do so. * Others @@ -156,7 +183,7 @@ Updates since v1.5.0 -- exec >/var/tmp/1 -O=v1.5.0.5-446-g5d86501 +O=v1.5.1-rc1-63-g12d6697 echo O=`git describe master` git shortlog --no-merges $O..master ^maint diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 39ba8d135c..551c391615 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.1-rc1.GIT +DEF_VER=v1.5.1-rc2.GIT LF=' ' From 52c813f22fef784c0c66fb3cb18217489cbacf3a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Mon, 26 Mar 2007 02:34:41 +0100 Subject: [PATCH 071/130] gitweb: Add example of config file and how to generate projects list to gitweb/INSTALL Add simple example of config file (turning on and allowing override of a few %features). Also example config file and script to generate list of projects in a format that can be used as GITWEB_LIST / $projects_list. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/INSTALL | 45 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/gitweb/INSTALL b/gitweb/INSTALL index 371407dc23..6328e26f56 100644 --- a/gitweb/INSTALL +++ b/gitweb/INSTALL @@ -103,9 +103,25 @@ for gitweb (in gitweb/README). See the top of gitweb.perl file for examples of customizable options. +Config file example +~~~~~~~~~~~~~~~~~~~ -Gitweb repositories: --------------------- +To enable blame, pickaxe search, and snapshot support, while allowing +individual projects to turn them off, put the following in your +GITWEB_CONFIG file: + + $feature{'blame'}{'default'} = [1]; + $feature{'blame'}{'override'} = 1; + + $feature{'pickaxe'}{'default'} = [1]; + $feature{'pickaxe'}{'override'} = 1; + + $feature{'snapshot'}{'default'} = ['x-gzip', 'gz', 'gzip']; + $feature{'snapshot'}{'override'} = 1; + + +Gitweb repositories +------------------- - By default all git repositories under projectroot are visible and available to gitweb. List of projects is generated by default by @@ -139,6 +155,31 @@ Gitweb repositories: show repository only if this file exists in its object database (if directory has the magic file $export_ok). +Generating projects list using gitweb +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +We assume that GITWEB_CONFIG has its default Makefile value, namely +gitweb_config.perl. Put the following in gitweb_make_index.perl file: + + $GITWEB_CONFIG = "gitweb_config.perl"; + do $GITWEB_CONFIG if -e $GITWEB_CONFIG; + + $projects_list = $projectroot; + +Then create the following script to get list of project in the format +suitable for GITWEB_LIST build configuration variable (or +$projects_list variable in gitweb config): + + #!/bin/sh + + export GITWEB_CONFIG="gitweb_make_index.perl" + export GATEWAY_INTERFACE="CGI/1.1" + export HTTP_ACCEPT="*/*" + export REQUEST_METHOD="GET" + export QUERY_STRING="a=project_index" + + perl -- /var/www/cgi-bin/gitweb.cgi + Requirements ------------ From c0ce981f5ebfd02463ff697b2fca52c7a54b0625 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Mon, 26 Mar 2007 06:14:40 +0200 Subject: [PATCH 072/130] Bisect: Use "git-show-ref --verify" when reseting. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- git-bisect.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-bisect.sh b/git-bisect.sh index 936b4a4b83..fda1712a08 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -173,7 +173,7 @@ bisect_reset() { else branch=master fi ;; - 1) test -f "$GIT_DIR/refs/heads/$1" || { + 1) git-show-ref --verify --quiet -- "refs/heads/$1" || { echo >&2 "$1 does not seem to be a valid branch" exit 1 } From e4d9516b2196623d927e232b4e8766269a837fe6 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Mon, 26 Mar 2007 14:55:39 -0400 Subject: [PATCH 073/130] git-rm: don't remove newly added file without -f Given this set of commands: $ echo "newly added file" >new $ git add new $ git rm new the file "new" was previously removed from the working directory and the index. Because it was not in HEAD, it is available only by searching for unreachable objects. Instead, we now err on the safe side and refuse to remove a file which is not referenced by HEAD. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin-rm.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/builtin-rm.c b/builtin-rm.c index 00dbe39960..bf42003a7e 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -89,20 +89,10 @@ static int check_local_mod(unsigned char *head) if (ce_match_stat(ce, &st, 0)) errs = error("'%s' has local modifications " "(hint: try -f)", ce->name); - if (no_head) - continue; - /* - * It is Ok to remove a newly added path, as long as - * it is cache-clean. - */ - if (get_tree_entry(head, name, sha1, &mode)) - continue; - /* - * Otherwise make sure the version from the HEAD - * matches the index. - */ - if (ce->ce_mode != create_ce_mode(mode) || - hashcmp(ce->sha1, sha1)) + if (no_head + || get_tree_entry(head, name, sha1, &mode) + || ce->ce_mode != create_ce_mode(mode) + || hashcmp(ce->sha1, sha1)) errs = error("'%s' has changes staged in the index " "(hint: try -f)", name); } From 0d315468f38729ebb15711349cece98a467032c9 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Mon, 26 Mar 2007 15:57:23 +0200 Subject: [PATCH 074/130] sha1_file.c (write_sha1_from_fd): Detect close failure. I stumbled across this in the context of the fchmod 0444 patch. At first, I was going to unlink and call error like the two subsequent tests do, but a failed write (above) provokes a "die", so I made this do the same. This is testing for a write failure, after all. Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- sha1_file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sha1_file.c b/sha1_file.c index 0897b945e5..42aef331f2 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2155,7 +2155,8 @@ int write_sha1_from_fd(const unsigned char *sha1, int fd, char *buffer, inflateEnd(&stream); fchmod(local, 0444); - close(local); + if (close(local) != 0) + die("unable to write sha1 file"); SHA1_Final(real_sha1, &c); if (ret != Z_STREAM_END) { unlink(tmpfile); From 8302012097f68caba5be82ba37b191b317886f2b Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 27 Mar 2007 06:49:57 +0200 Subject: [PATCH 075/130] Bisect: add checks at the beginning of "git bisect run". We may be able to "run" with only one good revision given and then verify that the result of the first run is bad. And perhaps also the other way around. But for now let's check that we have at least one bad and one good revision before we start to run. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- git-bisect.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/git-bisect.sh b/git-bisect.sh index fda1712a08..57d6754d34 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -223,6 +223,14 @@ bisect_replay () { } bisect_run () { + # Check that we have everything to run correctly. + test -d "$GIT_DIR/refs/bisect" || { + echo >&2 'You need to start by "git bisect start".' + echo >&2 'And then by "git bisect bad" and "git bisect good".' + exit 1 + } + bisect_next_check fail + while true do echo "running $@" From 89d589238988bce7a7bf5409561ae094197630e1 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 27 Mar 2007 12:51:13 -0700 Subject: [PATCH 076/130] Document git-log --first-parent Signed-off-by: Junio C Hamano --- Documentation/git-log.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt index 361eaec700..030edaf305 100644 --- a/Documentation/git-log.txt +++ b/Documentation/git-log.txt @@ -38,6 +38,11 @@ include::pretty-formats.txt[] and , see "SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1]. +--first-parent:: + Follow only the first parent commit upon seeing a merge + commit. This option gives a better overview of the + evolution of a particular branch. + -p:: Show the change the commit introduces in a patch form. From b704e589f411d51c7240d104d88422aa2d757822 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 26 Mar 2007 12:16:16 +0200 Subject: [PATCH 077/130] git.el: Display some information about the HEAD commit. Use git-log --pretty=oneline to print a short description of the current HEAD (and merge heads if any) in the buffer header. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- contrib/emacs/git.el | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el index 5f22dec5f7..2f9995ea39 100644 --- a/contrib/emacs/git.el +++ b/contrib/emacs/git.el @@ -263,6 +263,16 @@ and returns the process output as a string." (locale-charset-to-coding-system repo-config)) 'utf-8))) +(defun git-get-logoutput-coding-system () + "Return the coding system used for git-log output." + (let ((repo-config (or (git-config "i18n.logoutputencoding") + (git-config "i18n.commitencoding")))) + (or git-commits-coding-system + (and repo-config + (fboundp 'locale-charset-to-coding-system) + (locale-charset-to-coding-system repo-config)) + 'utf-8))) + (defun git-escape-file-name (name) "Escape a file name if necessary." (if (string-match "[\n\t\"\\]" name) @@ -406,6 +416,14 @@ and returns the process output as a string." (push (match-string 0) heads)))) (nreverse heads))) +(defun git-get-commit-description (commit) + "Get a one-line description of COMMIT." + (let ((coding-system-for-read (git-get-logoutput-coding-system))) + (let ((descr (git-call-process-env-string nil "log" "--max-count=1" "--pretty=oneline" commit))) + (if (and descr (string-match "\\`\\([0-9a-f]\\{40\\}\\) *\\(.*\\)$" descr)) + (concat (substring (match-string 1 descr) 0 10) " - " (match-string 2 descr)) + descr)))) + ;;;; File info structure ;;;; ------------------------------------------------------------ @@ -573,7 +591,7 @@ and returns the process output as a string." "Refresh the ewoc header and footer." (let ((branch (git-symbolic-ref "HEAD")) (head (if (git-empty-db-p) "Nothing committed yet" - (substring (git-rev-parse "HEAD") 0 10))) + (git-get-commit-description "HEAD"))) (merge-heads (git-get-merge-heads))) (ewoc-set-hf status (format "Directory: %s\nBranch: %s\nHead: %s%s\n" @@ -584,7 +602,7 @@ and returns the process output as a string." head (if merge-heads (concat "\nMerging: " - (mapconcat (lambda (str) (substring str 0 10)) merge-heads " ")) + (mapconcat (lambda (str) (git-get-commit-description str)) merge-heads "\n ")) "")) (if (ewoc-nth status 0) "" " No changes.")))) From e82973cfb046b4298114368e6d194a3418f2a30c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 27 Mar 2007 12:55:44 -0700 Subject: [PATCH 078/130] sha1_file.c (write_sha1_file): Detect close failure This is in the same spirit as earlier fix to write_sha1_from_fd(). Signed-off-by: Junio C Hamano --- sha1_file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sha1_file.c b/sha1_file.c index 42aef331f2..9c26038420 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2020,7 +2020,8 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha if (write_buffer(fd, compressed, size) < 0) die("unable to write sha1 file"); fchmod(fd, 0444); - close(fd); + if (close(fd)) + die("unable to write sha1 file"); free(compressed); return move_temp_to_file(tmpfile, filename); From f73bbb2d0cdbd0153b7a2b7cd5bab72d1b495a45 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 27 Mar 2007 02:07:11 +0200 Subject: [PATCH 079/130] gitweb: Cleanup and uniquify die_error calls Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 5214050a88..3348583227 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3154,7 +3154,7 @@ sub git_blame2 { } $ftype = git_get_type($hash); if ($ftype !~ "blob") { - die_error("400 Bad Request", "Object is not a blob"); + die_error('400 Bad Request', "Object is not a blob"); } open ($fd, "-|", git_cmd(), "blame", '-p', '--', $file_name, $hash_base) @@ -3220,7 +3220,7 @@ HTML print "\n"; } open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^") - or die_error("could not open git-rev-parse"); + or die_error(undef, "Open git-rev-parse failed"); my $parent_commit = <$dd>; close $dd; chomp($parent_commit); @@ -3622,7 +3622,7 @@ sub git_snapshot { $name =~ s/\047/\047\\\047\047/g; open my $fd, "-|", "$git archive --format=tar --prefix=\'$name\'/ $hash | $command" - or die_error(undef, "Execute git-tar-tree failed."); + or die_error(undef, "Execute git-tar-tree failed"); binmode STDOUT, ':raw'; print <$fd>; binmode STDOUT, ':utf8'; # as set at the beginning of gitweb.cgi From 66d5871ead74ae363274f221c9fa5945c18c4aa2 Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Tue, 27 Mar 2007 10:13:42 +0000 Subject: [PATCH 080/130] Makefile: remove test-chmtime program in target clean. While running 'make test', the test-chmtime program is created, and should be cleaned up on 'make clean'. Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 51c1fed711..960f98e801 100644 --- a/Makefile +++ b/Makefile @@ -963,7 +963,7 @@ dist-doc: clean: rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \ - $(LIB_FILE) $(XDIFF_LIB) + test-chmtime$X $(LIB_FILE) $(XDIFF_LIB) rm -f $(ALL_PROGRAMS) $(BUILT_INS) git$X rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags rm -rf autom4te.cache From 608d48b2207a6152839a9762c7a66f217bceb440 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Tue, 27 Mar 2007 09:50:20 -0700 Subject: [PATCH 081/130] Fix "getaddrinfo()" buglet At least in Linux glibc, "getaddrinfo()" has a very irritating feature (or bug, who knows..). Namely if you pass it in an empty string for the service name, it will happily and quietly consider it identical to a NULL port pointer, and return port number zero and no errors. Which obviously will not work. Maybe that's what it's really expected to do, although the man-page for getaddrinfo() certainly implies that it's a bug. So when somebody passes me a "please pull" request pointing to something like the following git://git.kernel.org:/pub/scm/linux/kernel/git/mchehab/v4l-dvb.git (note the extraneous colon at the end of the host name), git would happily try to connect to port 0, which would generally just cause the remote to not even answer, and the "connect()" will take a long time to time out. So to work around the glibc feature/bug, just notice this empty port case automatically. Also, add the port information to the error information when it fails to look up (maybe it's the host-name that fails, maybe it's the port-name - we should print out both). Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- connect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/connect.c b/connect.c index 5048653639..da89c9cfcf 100644 --- a/connect.c +++ b/connect.c @@ -417,6 +417,8 @@ static int git_tcp_connect_sock(char *host) if (colon) { *colon = 0; port = colon + 1; + if (!*port) + port = ""; } memset(&hints, 0, sizeof(hints)); @@ -425,7 +427,7 @@ static int git_tcp_connect_sock(char *host) gai = getaddrinfo(host, port, &hints, &ai); if (gai) - die("Unable to look up %s (%s)", host, gai_strerror(gai)); + die("Unable to look up %s (port %s) (%s)", host, port, gai_strerror(gai)); for (ai0 = ai; ai; ai = ai->ai_next) { sockfd = socket(ai->ai_family, From aa4cfa8516f33ccde36b6cadf3dab2ddefb972af Mon Sep 17 00:00:00 2001 From: James Bowes Date: Tue, 27 Mar 2007 18:30:19 -0400 Subject: [PATCH 082/130] read-tree: use xcalloc Signed-off-by: James Bowes Signed-off-by: Junio C Hamano --- builtin-read-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-read-tree.c b/builtin-read-tree.c index 82df94101a..793eae0a5f 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -184,7 +184,7 @@ int cmd_read_tree(int argc, const char **argv, const char *unused_prefix) if (opts.dir) die("more than one --exclude-per-directory are given."); - dir = calloc(1, sizeof(*opts.dir)); + dir = xcalloc(1, sizeof(*opts.dir)); dir->show_ignored = 1; dir->exclude_per_dir = arg + 24; opts.dir = dir; From c6e0caa3846f05831c1d4785ef373820c75eba2b Mon Sep 17 00:00:00 2001 From: James Bowes Date: Tue, 27 Mar 2007 18:30:08 -0400 Subject: [PATCH 083/130] use xrealloc in help.c Signed-off-by: James Bowes Signed-off-by: Junio C Hamano --- help.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/help.c b/help.c index be8651a739..6a9af4d175 100644 --- a/help.c +++ b/help.c @@ -31,12 +31,6 @@ static int term_columns(void) return 80; } -static void oom(void) -{ - fprintf(stderr, "git: out of memory\n"); - exit(1); -} - static inline void mput_char(char c, unsigned int num) { while(num--) @@ -54,13 +48,9 @@ static void add_cmdname(const char *name, int len) struct cmdname *ent; if (cmdname_alloc <= cmdname_cnt) { cmdname_alloc = cmdname_alloc + 200; - cmdname = realloc(cmdname, cmdname_alloc * sizeof(*cmdname)); - if (!cmdname) - oom(); + cmdname = xrealloc(cmdname, cmdname_alloc * sizeof(*cmdname)); } ent = xmalloc(sizeof(*ent) + len); - if (!ent) - oom(); ent->len = len; memcpy(ent->name, name, len); ent->name[len] = 0; From 4621af371686f5c787c172c285562ad997281821 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 27 Mar 2007 19:26:28 -0400 Subject: [PATCH 084/130] --pretty=format: fix broken %ct and %at interpolation A pointer arithmetic error in fill_person caused random data from the commit object to be included with the timestamp, which looked something like: $ git-rev-list --pretty=format:%ct origin/next | head commit 98453bdb3db10db26099749bc4f2dc029bed9aa9 1174977948 -0700 Merge branch 'master' into next * master: Bisect: Use commit c0ce981f5ebfd02463ff697b2fca52c7a54b0625 1174889646 -0700 Signed-off-by: Jeff King Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commit.c b/commit.c index 718e568855..a92958cfac 100644 --- a/commit.c +++ b/commit.c @@ -760,7 +760,7 @@ static void fill_person(struct interp *table, const char *msg, int len) if (msg + start == ep) return; - table[5].value = xstrndup(msg + start, ep - msg + start); + table[5].value = xstrndup(msg + start, ep - (msg + start)); /* parse tz */ for (start = ep - msg + 1; start < len && isspace(msg[start]); start++) From 465b3518a9ad5080a4b652ef35fb13c61a93e7a4 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 27 Mar 2007 16:45:06 -0700 Subject: [PATCH 085/130] git-upload-pack: make sure we close unused pipe ends Right now, we don't close the read end of the pipe when git-upload-pack runs git-pack-object, so we hang forever (why don't we get SIGALRM?) instead of dying with SIGPIPE if the latter dies, which seems to be the norm if the client disconnects. Thanks to Johannes Schindelin for pointing out where this close() needed to go. This patch has been tested on kernel.org for several weeks and appear to resolve the problem of git-upload-pack processes hanging around forever. Signed-off-by: H. Peter Anvin Signed-off-by: Junio C Hamano --- upload-pack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/upload-pack.c b/upload-pack.c index 498bf50eb8..d3a09e78d5 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -119,6 +119,7 @@ static void create_pack_file(void) int i; struct rev_info revs; + close(lp_pipe[0]); pack_pipe = fdopen(lp_pipe[1], "w"); if (create_full_pack) From fa21b6023288d5ee0afa79021493a199b1c9bac5 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 27 Mar 2007 20:08:28 -0400 Subject: [PATCH 086/130] Add some basic tests of rev-list --pretty=format These could stand to be a little more complex, but it should at least catch obvious problems (like the recently fixed %ct bug). Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- t/t6006-rev-list-format.sh | 108 +++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 t/t6006-rev-list-format.sh diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh new file mode 100644 index 0000000000..cf096c3579 --- /dev/null +++ b/t/t6006-rev-list-format.sh @@ -0,0 +1,108 @@ +#!/bin/sh + +test_description='git-rev-list --pretty=format test' + +. ./test-lib.sh + +test_tick +test_expect_success 'setup' ' +touch foo && git-add foo && git-commit -m "added foo" && + echo changed >foo && git-commit -a -m "changed foo" +' + +# usage: test_format name format_string expect.$1 + test_expect_success "format $1" " +git-rev-list --pretty=format:$2 master >output.$1 && +git-diff expect.$1 output.$1 +" +} + +test_format hash %H%n%h <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +131a310eb913d107dd3c09a65d1651175898735d +131a310 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf +EOF + +test_format tree %T%n%t <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +fe722612f26da5064c32ca3843aa154bdb0b08a0 +fe72261 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +4d5fcadc293a348e88f777dc0920f11e7d71441c +4d5fcad +EOF + +test_format parents %P%n%p <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf +86c75cf +EOF + +# we don't test relative here +test_format author %an%n%ae%n%ad%n%aD%n%at <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +A U Thor +author@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +A U Thor +author@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +EOF + +test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +C O Mitter +committer@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +C O Mitter +committer@example.com +Thu Apr 7 15:13:13 2005 -0700 +Thu, 7 Apr 2005 15:13:13 -0700 +1112911993 +EOF + +test_format encoding %e <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d + +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 + +EOF + +test_format subject %s <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +changed foo +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +added foo +EOF + +test_format body %b <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d + +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 + +EOF + +test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<'EOF' +commit 131a310eb913d107dd3c09a65d1651175898735d +foobarbazxyzzy +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +foobarbazxyzzy +EOF + +test_done From d3e41ebff44745055001e59e460509a8f04b81a2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 28 Mar 2007 03:05:08 -0700 Subject: [PATCH 087/130] git-commit: "read-tree -m HEAD" is not the right way to read-tree quickly It still looks at the working tree and checks for locally modified paths. When are preparing a temporary index from HEAD, we do not want any of that. Signed-off-by: Junio C Hamano --- git-commit.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-commit.sh b/git-commit.sh index cad16a5e86..fdaedc0e2e 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -360,7 +360,7 @@ t,) if test -z "$initial_commit" then cp "$THIS_INDEX" "$TMP_INDEX" - GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -m HEAD + GIT_INDEX_FILE="$TMP_INDEX" git-read-tree -i -m HEAD else rm -f "$TMP_INDEX" fi || exit From 2afea3bcd2a2b3327d7e8bdabc9aebd6bef24c6e Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Wed, 28 Mar 2007 09:46:15 +0000 Subject: [PATCH 088/130] http-fetch: don't use double-slash as directory separator in URLs Please see http://bugs.debian.org/409887 http-fetch expected the URL given at the command line to have a trailing slash anyway, and then added '/objects...' when requesting objects files from the http server. Now it doesn't require the trailing slash in anymore, and strips trailing slashes if given nonetheless. Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- git-clone.sh | 2 +- git-fetch.sh | 2 +- http-fetch.c | 21 ++++++++++++--------- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/git-clone.sh b/git-clone.sh index 6ba477d1f4..513b574d13 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -60,7 +60,7 @@ Perhaps git-update-server-info needs to be run there?" else tname=$name fi - git-http-fetch $v -a -w "$tname" "$name" "$1/" || exit 1 + git-http-fetch $v -a -w "$tname" "$name" "$1" || exit 1 done <"$clone_tmp/refs" rm -fr "$clone_tmp" http_fetch "$1/HEAD" "$GIT_DIR/REMOTE_HEAD" || diff --git a/git-fetch.sh b/git-fetch.sh index 93349330d4..fd70696b74 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -248,7 +248,7 @@ fetch_per_ref () { expr "z$head" : "z$_x40\$" >/dev/null || die "No such ref $remote_name at $remote" echo >&2 "Fetching $remote_name from $remote using $proto" - git-http-fetch -v -a "$head" "$remote/" || exit + git-http-fetch -v -a "$head" "$remote" || exit ;; rsync://*) test -n "$shallow_depth" && diff --git a/http-fetch.c b/http-fetch.c index e6cd11db73..58b77a7a18 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -16,7 +16,7 @@ static struct curl_slist *no_pragma_header; struct alt_base { - const char *base; + char *base; int path_len; int got_indices; struct packed_git *packs; @@ -158,12 +158,12 @@ static void start_object_request(struct object_request *obj_req) SHA1_Init(&obj_req->c); - url = xmalloc(strlen(obj_req->repo->base) + 50); - obj_req->url = xmalloc(strlen(obj_req->repo->base) + 50); + url = xmalloc(strlen(obj_req->repo->base) + 51); + obj_req->url = xmalloc(strlen(obj_req->repo->base) + 51); strcpy(url, obj_req->repo->base); posn = url + strlen(obj_req->repo->base); - strcpy(posn, "objects/"); - posn += 8; + strcpy(posn, "/objects/"); + posn += 9; memcpy(posn, hex, 2); posn += 2; *(posn++) = '/'; @@ -938,14 +938,14 @@ static char *quote_ref_url(const char *base, const char *ref) int len, baselen, ch; baselen = strlen(base); - len = baselen + 6; /* "refs/" + NUL */ + len = baselen + 7; /* "/refs/" + NUL */ for (cp = ref; (ch = *cp) != 0; cp++, len++) if (needs_quote(ch)) len += 2; /* extra two hex plus replacement % */ qref = xmalloc(len); memcpy(qref, base, baselen); - memcpy(qref + baselen, "refs/", 5); - for (cp = ref, dp = qref + baselen + 5; (ch = *cp) != 0; cp++) { + memcpy(qref + baselen, "/refs/", 6); + for (cp = ref, dp = qref + baselen + 6; (ch = *cp) != 0; cp++) { if (needs_quote(ch)) { *dp++ = '%'; *dp++ = hex((ch >> 4) & 0xF); @@ -1044,7 +1044,10 @@ int main(int argc, const char **argv) no_pragma_header = curl_slist_append(no_pragma_header, "Pragma:"); alt = xmalloc(sizeof(*alt)); - alt->base = url; + alt->base = xmalloc(strlen(url) + 1); + strcpy(alt->base, url); + for (path = alt->base + strlen(alt->base) - 1; *path == '/'; --path) + *path = 0; alt->got_indices = 0; alt->packs = NULL; alt->next = NULL; From 9c880b3ea56a7ff2f66dcf12eb2351f0f51a54ef Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Wed, 28 Mar 2007 09:47:35 +0000 Subject: [PATCH 089/130] http-fetch: remove path_len from struct alt_base, it was computed but never used Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- http-fetch.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/http-fetch.c b/http-fetch.c index 58b77a7a18..557b40322f 100644 --- a/http-fetch.c +++ b/http-fetch.c @@ -17,7 +17,6 @@ static struct curl_slist *no_pragma_header; struct alt_base { char *base; - int path_len; int got_indices; struct packed_git *packs; struct alt_base *next; @@ -515,7 +514,6 @@ static void process_alternates_response(void *callback_data) int serverlen = 0; struct alt_base *newalt; char *target = NULL; - char *path; if (data[i] == '/') { /* This counts * http://git.host/pub/scm/linux.git/ @@ -583,12 +581,6 @@ static void process_alternates_response(void *callback_data) newalt->base = target; newalt->got_indices = 0; newalt->packs = NULL; - path = strstr(target, "//"); - if (path) { - path = strchr(path+2, '/'); - if (path) - newalt->path_len = strlen(path); - } while (tail->next != NULL) tail = tail->next; @@ -999,7 +991,7 @@ int main(int argc, const char **argv) const char **write_ref = NULL; char **commit_id; const char *url; - char *path; + char *s; int arg = 1; int rc = 0; @@ -1046,17 +1038,11 @@ int main(int argc, const char **argv) alt = xmalloc(sizeof(*alt)); alt->base = xmalloc(strlen(url) + 1); strcpy(alt->base, url); - for (path = alt->base + strlen(alt->base) - 1; *path == '/'; --path) - *path = 0; + for (s = alt->base + strlen(alt->base) - 1; *s == '/'; --s) + *s = 0; alt->got_indices = 0; alt->packs = NULL; alt->next = NULL; - path = strstr(url, "//"); - if (path) { - path = strchr(path+2, '/'); - if (path) - alt->path_len = strlen(path); - } if (pull(commits, commit_id, write_ref, url)) rc = 1; From 542e165cdc4fbebbfe7c8954ca1aa1d4162e38cb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 28 Mar 2007 13:33:37 -0700 Subject: [PATCH 090/130] Fix "--pretty=format:" for parent related items. There are two breakages in the %P/%p interpolation. It appended an excess SP at the end of the list, and it gave uninitialized contents of a buffer on the stack for root commits. This fixes it, while updating the t6006 test which expected the wrong output. Signed-off-by: Junio C Hamano --- commit.c | 12 ++++++++---- t/t6006-rev-list-format.sh | 8 ++++---- 2 files changed, 12 insertions(+), 8 deletions(-) mode change 100644 => 100755 t/t6006-rev-list-format.sh diff --git a/commit.c b/commit.c index a92958cfac..9ac533c85a 100644 --- a/commit.c +++ b/commit.c @@ -849,19 +849,23 @@ static long format_commit_message(const struct commit *commit, interp_set_entry(table, ITREE_ABBREV, find_unique_abbrev(commit->tree->object.sha1, DEFAULT_ABBREV)); + + parents[1] = 0; for (i = 0, p = commit->parents; p && i < sizeof(parents) - 1; p = p->next) - i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ", + i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", sha1_to_hex(p->item->object.sha1)); - interp_set_entry(table, IPARENTS, parents); + interp_set_entry(table, IPARENTS, parents + 1); + + parents[1] = 0; for (i = 0, p = commit->parents; p && i < sizeof(parents) - 1; p = p->next) - i += snprintf(parents + i, sizeof(parents) - i - 1, "%s ", + i += snprintf(parents + i, sizeof(parents) - i - 1, " %s", find_unique_abbrev(p->item->object.sha1, DEFAULT_ABBREV)); - interp_set_entry(table, IPARENTS_ABBREV, parents); + interp_set_entry(table, IPARENTS_ABBREV, parents + 1); for (i = 0, state = HEADER; msg[i] && state < BODY; i++) { int eol; diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh old mode 100644 new mode 100755 index cf096c3579..ce9c7dc6eb --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -39,11 +39,11 @@ EOF test_format parents %P%n%p <<'EOF' commit 131a310eb913d107dd3c09a65d1651175898735d -86c75cfd708a0e5868dc876ed5b8bb66c80b4873 -86c75cf +86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +86c75cf commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 -86c75cf -86c75cf + + EOF # we don't test relative here From 6a5ea2d023906a6e8feea42afa45536db6fd493f Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 28 Mar 2007 17:09:05 -0400 Subject: [PATCH 091/130] Fix "--pretty=format:" encoding item It printed the header "encoding " instead of just showing the encoding, as all other items do. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- commit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/commit.c b/commit.c index 9ac533c85a..a4f2e74c0b 100644 --- a/commit.c +++ b/commit.c @@ -888,7 +888,8 @@ static long format_commit_message(const struct commit *commit, fill_person(table + ICOMMITTER_NAME, msg + i + 10, eol - i - 10); else if (!prefixcmp(msg + i, "encoding ")) - table[IENCODING].value = xstrndup(msg + i, eol - i); + table[IENCODING].value = + xstrndup(msg + i + 9, eol - i - 9); i = eol; } if (msg[i]) From 03bcaacaadbb325f412e6dffec27fea6acb9321e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 28 Mar 2007 17:08:36 -0400 Subject: [PATCH 092/130] t/t6006: add tests for a slightly more complex commit messages Especially this tests i18n messages and encoding header. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- t/t6006-rev-list-format.sh | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh index ce9c7dc6eb..aab17face8 100755 --- a/t/t6006-rev-list-format.sh +++ b/t/t6006-rev-list-format.sh @@ -105,4 +105,46 @@ commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 foobarbazxyzzy EOF +cat >commit-msg <<'EOF' +Test printing of complex bodies + +This commit message is much longer than the others, +and it will be encoded in iso8859-1. We should therefore +include an iso8859 character: ¡bueno! +EOF +test_expect_success 'setup complex body' ' +git-config i18n.commitencoding iso8859-1 && + echo change2 >foo && git-commit -a -F commit-msg +' + +test_format complex-encoding %e <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +iso8859-1 +commit 131a310eb913d107dd3c09a65d1651175898735d + +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 + +EOF + +test_format complex-subject %s <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +Test printing of complex bodies +commit 131a310eb913d107dd3c09a65d1651175898735d +changed foo +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 +added foo +EOF + +test_format complex-body %b <<'EOF' +commit f58db70b055c5718631e5c61528b28b12090cdea +This commit message is much longer than the others, +and it will be encoded in iso8859-1. We should therefore +include an iso8859 character: ¡bueno! + +commit 131a310eb913d107dd3c09a65d1651175898735d + +commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873 + +EOF + test_done From 75c962c99a9115d489549ad9b8419d3e37e85f02 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 22 Mar 2007 21:05:28 -0400 Subject: [PATCH 093/130] t4118: be nice to non-GNU sed Elias Pipping: > I'm on a mac, hence /usr/bin/sed is not gnu sed, which makes > t4118 fail. Signed-off-by: Johannes Schindelin Ack'd-by: Elias Pipping Signed-off-by: Junio C Hamano --- t/t4118-apply-empty-context.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/t/t4118-apply-empty-context.sh b/t/t4118-apply-empty-context.sh index 7309422fe5..e78b1a1a79 100755 --- a/t/t4118-apply-empty-context.sh +++ b/t/t4118-apply-empty-context.sh @@ -23,7 +23,8 @@ test_expect_success setup ' cat file2 >file2.orig git add file1 file2 && sed -e "/^B/d" file1 && - sed -e "/^B/d" file2 && + sed -e "/^[BQ]/d" file2 && + echo Q | tr -d "\\012" >>file2 && cat file1 >file1.mods && cat file2 >file2.mods && git diff | From d0e50cb4cb8e0cc8b445a9749547019efaa5703e Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 28 Mar 2007 17:52:09 -0400 Subject: [PATCH 094/130] commit: fix pretty-printing of messages with "\nencoding " The function replace_encoding_header is given the whole commit buffer, including the commit message. When looking for the encoding header, if none was found in the header, it would locate any line in the commit message matching "\nencoding " and remove it. Instead, we now make sure to search only to the end of the header. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- commit.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/commit.c b/commit.c index 3e8c87294b..1fe23b6e3a 100644 --- a/commit.c +++ b/commit.c @@ -644,6 +644,7 @@ static char *get_header(const struct commit *commit, const char *key) static char *replace_encoding_header(char *buf, char *encoding) { char *encoding_header = strstr(buf, "\nencoding "); + char *header_end = strstr(buf, "\n\n"); char *end_of_encoding_header; int encoding_header_pos; int encoding_header_len; @@ -651,8 +652,10 @@ static char *replace_encoding_header(char *buf, char *encoding) int need_len; int buflen = strlen(buf) + 1; - if (!encoding_header) - return buf; /* should not happen but be defensive */ + if (!header_end) + header_end = buf + buflen; + if (!encoding_header || encoding_header >= header_end) + return buf; encoding_header++; end_of_encoding_header = strchr(encoding_header, '\n'); if (!end_of_encoding_header) From 9529a2524a29c15107905f2f8f0b310a40880dc7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 28 Mar 2007 13:53:00 -0700 Subject: [PATCH 095/130] GIT 1.5.0.6 --- Documentation/RelNotes-1.5.0.6.txt | 22 ++++++++++++++++++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes-1.5.0.6.txt diff --git a/Documentation/RelNotes-1.5.0.6.txt b/Documentation/RelNotes-1.5.0.6.txt new file mode 100644 index 0000000000..e15447ffdb --- /dev/null +++ b/Documentation/RelNotes-1.5.0.6.txt @@ -0,0 +1,22 @@ +GIT v1.5.0.6 Release Notes +========================== + +Fixes since v1.5.0.5 +-------------------- + +* Bugfixes + + - a handful small fixes to gitweb. + + - build procedure for user-manual is fixed not to require locally + installed stylesheets. + + - "git commit $paths" on paths whose earlier contents were + already updated in the index were failing out. + +* Documentation + + - user-manual has better cross references. + + - gitweb installation/deployment procedure is now documented. + diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 3f41a87bed..6abd4cfc98 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.0.5.GIT +DEF_VER=v1.5.0.6.GIT LF=' ' diff --git a/RelNotes b/RelNotes index 8877578a8a..4e145f3021 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes-1.5.0.5.txt \ No newline at end of file +Documentation/RelNotes-1.5.0.6.txt \ No newline at end of file From 43a8e4fe8e3c92fc15ae16b818d44241568d484e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 28 Mar 2007 15:40:17 -0700 Subject: [PATCH 096/130] Update main git.html page to point at 1.5.0.6 documentation Signed-off-by: Junio C Hamano --- Documentation/git.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index 31397dc539..dceacfac11 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -35,7 +35,9 @@ ifdef::stalenotes[] You are reading the documentation for the latest version of git. Documentation for older releases are available here: -* link:v1.5.0.5/git.html[documentation for release 1.5.0.5] +* link:v1.5.0.6/git.html[documentation for release 1.5.0.6] + +* link:v1.5.0.6/RelNotes-1.5.0.6.txt[release notes for 1.5.0.6] * link:v1.5.0.5/RelNotes-1.5.0.5.txt[release notes for 1.5.0.5] From 7685227e973fce34340d3766b1775263751afa56 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 28 Mar 2007 15:58:09 -0700 Subject: [PATCH 097/130] GIT 1.5.1-rc3 --- GIT-VERSION-GEN | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 551c391615..601f30f311 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.1-rc2.GIT +DEF_VER=v1.5.1-rc3.GIT LF=' ' From 3e63e0df4f1a1610782e679be56ea75f820343fc Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Thu, 29 Mar 2007 06:41:42 +0000 Subject: [PATCH 098/130] Documentation/git-svnimport.txt: fix typo. This was noticed by Frederik Schwarzer. SVN's repository by default has trunk, tags/, and branch_es_/. Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- Documentation/git-svnimport.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index b166cf3327..bdae7d87dc 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -27,7 +27,7 @@ repository, or incrementally import into an existing one. SVN access is done by the SVN::Perl module. git-svnimport assumes that SVN repositories are organized into one -"trunk" directory where the main development happens, "branch/FOO" +"trunk" directory where the main development happens, "branches/FOO" directories for branches, and "/tags/FOO" directories for tags. Other subdirectories are ignored. From c2c6d9302a98ae4c4c76822a1c83551c039271a0 Mon Sep 17 00:00:00 2001 From: Gerrit Pape Date: Thu, 29 Mar 2007 06:42:44 +0000 Subject: [PATCH 099/130] Documentation/git-rev-parse.txt: fix example in SPECIFYING RANGES. Please see http://bugs.debian.org/404795: In git-rev-parse(1), there is an example commit tree, which is used twice. The explanation for this tree is very clear: B and C are commit *parents* to A. However, when the tree is reused as an example in the SPECIFYING RANGES, the manpage author screws up and uses A as a commit *parent* to B and C! I.e., he inverts the tree. And the fact that for this example you need to read the tree backwards is not explained anywhere (and it would be confusing even if it was). Signed-off-by: Gerrit Pape Signed-off-by: Junio C Hamano --- Documentation/git-rev-parse.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt index 4041a16070..d0a2ad3088 100644 --- a/Documentation/git-rev-parse.txt +++ b/Documentation/git-rev-parse.txt @@ -258,14 +258,14 @@ its all parents. Here are a handful examples: - D A B D - D F A B C D F - ^A G B D - ^A F B C F - G...I C D F G I - ^B G I C D F G I - F^@ A B C - F^! H D F H + D G H D + D F G H I J D F + ^G D H D + ^D B E I J F B + B...C G H D E B C + ^D B C E I J F B C + C^@ I J F + F^! D G H D F Author ------ From 3ac53e0d13fa7483cce90eb6a1cfcdcbda5b8e35 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 27 Mar 2007 16:45:06 -0700 Subject: [PATCH 100/130] git-upload-pack: make sure we close unused pipe ends Right now, we don't close the read end of the pipe when git-upload-pack runs git-pack-object, so we hang forever (why don't we get SIGALRM?) instead of dying with SIGPIPE if the latter dies, which seems to be the norm if the client disconnects. Thanks to Johannes Schindelin for pointing out where this close() needed to go. This patch has been tested on kernel.org for several weeks and appear to resolve the problem of git-upload-pack processes hanging around forever. Signed-off-by: H. Peter Anvin Signed-off-by: Junio C Hamano (cherry picked from commit 465b3518a9ad5080a4b652ef35fb13c61a93e7a4) --- upload-pack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/upload-pack.c b/upload-pack.c index 3648aae1a7..044c33b090 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -119,6 +119,7 @@ static void create_pack_file(void) int i; struct rev_info revs; + close(lp_pipe[0]); pack_pipe = fdopen(lp_pipe[1], "w"); if (create_full_pack) From e15b484f6af581270f2ee03149e4e0d6af053ddf Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 27 Mar 2007 11:38:59 -0400 Subject: [PATCH 101/130] Fix minor formatting issue in man page for git-mergetool Signed-off-by: "Theodore Ts'o" --- Documentation/git-mergetool.txt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index 5baaaca0b5..34288fe08b 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -26,11 +26,11 @@ OPTIONS Use the merge resolution program specified by . Valid merge tools are: kdiff3, tkdiff, meld, xxdiff, emerge, and vimdiff. - - If a merge resolution program is not specified, 'git mergetool' - will use the configuration variable merge.tool. If the - configuration variable merge.tool is not set, 'git mergetool' - will pick a suitable default. ++ +If a merge resolution program is not specified, 'git mergetool' +will use the configuration variable merge.tool. If the +configuration variable merge.tool is not set, 'git mergetool' +will pick a suitable default. Author ------ From 20fa04ea6bad985d74bd2c0180701f1c69272801 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 27 Mar 2007 12:12:22 -0400 Subject: [PATCH 102/130] mergetool: Replace use of "echo -n" with printf(1) to be more portable Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 7942fd0b64..3401823350 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -44,18 +44,16 @@ function describe_file () { branch="$2" file="$3" - echo -n " " + printf " " if test -z "$mode"; then - echo -n "'$path' was deleted" + printf "'%s' was deleted" "$path" elif is_symlink "$mode" ; then - echo -n "'$path' is a symlink containing '" - cat "$file" - echo -n "'" + printf "'%s' is a symlink containing '%s'" "$path" "$file" else if base_present; then - echo -n "'$path' was created" + printf "'%s' was created" "$path" else - echo -n "'$path' was modified" + printf "'%s' was modified" "$path" fi fi echo " in the $branch branch" @@ -64,7 +62,7 @@ function describe_file () { resolve_symlink_merge () { while /bin/true; do - echo -n "Use (r)emote or (l)ocal, or (a)bort? " + printf "Use (r)emote or (l)ocal, or (a)bort? " read ans case "$ans" in [lL]*) @@ -88,7 +86,7 @@ resolve_symlink_merge () { resolve_deleted_merge () { while /bin/true; do - echo -n "Use (m)odified or (d)eleted file, or (a)bort? " + printf "Use (m)odified or (d)eleted file, or (a)bort? " read ans case "$ans" in [mM]*) @@ -157,7 +155,7 @@ merge_file () { echo "Normal merge conflict for $path:" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" - echo -n "Hit return to start merge resolution tool ($merge_tool): " + printf "Hit return to start merge resolution tool (%s): " "$merge_tool" read ans case "$merge_tool" in @@ -193,7 +191,7 @@ merge_file () { else while true; do echo "$path seems unchanged." - echo -n "Was the merge successful? [y/n] " + printf "Was the merge successful? [y/n] " read answer < /dev/tty case "$answer" in y*|Y*) status=0; break ;; @@ -225,7 +223,7 @@ merge_file () { else while true; do echo "$path seems unchanged." - echo -n "Was the merge successful? [y/n] " + printf "Was the merge successful? [y/n] " read answer < /dev/tty case "$answer" in y*|Y*) status=0; break ;; @@ -346,12 +344,12 @@ if test $# -eq 0 ; then echo Merging the files: $files git ls-files -u | sed -e 's/^[^ ]* //' | sort -u | while read i do - echo "" + printf "\n" merge_file "$i" < /dev/tty > /dev/tty done else while test $# -gt 0; do - echo "" + printf "\n" merge_file "$1" shift done From ce5b6d752bf4fdc72697ef85b3589983f52d7007 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 27 Mar 2007 18:00:03 -0400 Subject: [PATCH 103/130] mergetool: Don't error out in the merge case where the local file is deleted If the file we are trying to merge resolve is in git-ls-files -u, then skip the file existence test. If the file isn't reported in git-ls-files, then check to see if the file exists or not to give an appropriate error message. Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 3401823350..fa301add3f 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -109,14 +109,13 @@ resolve_deleted_merge () { merge_file () { path="$1" - if test ! -f "$path" ; then - echo "$path: file not found" - exit 1 - fi - f=`git-ls-files -u -- "$path"` if test -z "$f" ; then - echo "$path: file does not need merging" + if test ! -f "$path" ; then + echo "$path: file not found" + else + echo "$path: file does not need merging" + fi exit 1 fi From d1dc6959bbff89496e3ae5d845d73e98ae213e09 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 06:46:59 -0400 Subject: [PATCH 104/130] mergetool: portability fix: don't assume true is in /bin Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index fa301add3f..600aef0a12 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -61,7 +61,7 @@ function describe_file () { resolve_symlink_merge () { - while /bin/true; do + while true; do printf "Use (r)emote or (l)ocal, or (a)bort? " read ans case "$ans" in @@ -85,7 +85,7 @@ resolve_symlink_merge () { } resolve_deleted_merge () { - while /bin/true; do + while true; do printf "Use (m)odified or (d)eleted file, or (a)bort? " read ans case "$ans" in From 262c981ea720c3c67d01d9a556069f79a6170786 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 06:55:11 -0400 Subject: [PATCH 105/130] mergetool: portability fix: don't use reserved word function Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 600aef0a12..0b843a54de 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -14,19 +14,19 @@ SUBDIRECTORY_OK=Yes require_work_tree # Returns true if the mode reflects a symlink -function is_symlink () { +is_symlink () { test "$1" = 120000 } -function local_present () { +local_present () { test -n "$local_mode" } -function remote_present () { +remote_present () { test -n "$remote_mode" } -function base_present () { +base_present () { test -n "$base_mode" } @@ -39,7 +39,7 @@ cleanup_temp_files () { fi } -function describe_file () { +describe_file () { mode="$1" branch="$2" file="$3" From ddc0c49753001d2b5da4df7df2d42378c8c3a295 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 09:39:59 -0400 Subject: [PATCH 106/130] mergetool: factor out common code Create common function check_unchanged(), save_backup() and remove_backup(). Also fix some minor whitespace issues while we're at it. Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 78 ++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 42 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 0b843a54de..1355fcb19f 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -106,12 +106,40 @@ resolve_deleted_merge () { done } +check_unchanged () { + if test "$path" -nt "$BACKUP" ; then + status=0; + else + while true; do + echo "$path seems unchanged." + printf "Was the merge successful? [y/n] " + read answer < /dev/tty + case "$answer" in + y*|Y*) status=0; break ;; + n*|N*) status=1; break ;; + esac + done + fi +} + +save_backup () { + if test "$status" -eq 0; then + mv -- "$BACKUP" "$path.orig" + fi +} + +remove_backup () { + if test "$status" -eq 0; then + rm "$BACKUP" + fi +} + merge_file () { path="$1" f=`git-ls-files -u -- "$path"` if test -z "$f" ; then - if test ! -f "$path" ; then + if test ! -f "$path" ; then echo "$path: file not found" else echo "$path: file does not need merging" @@ -167,9 +195,7 @@ merge_file () { -o "$path" -- "$LOCAL" "$REMOTE" > /dev/null 2>&1) fi status=$? - if test "$status" -eq 0; then - rm "$BACKUP" - fi + remove_backup ;; tkdiff) if base_present ; then @@ -178,29 +204,13 @@ merge_file () { tkdiff -o "$path" -- "$LOCAL" "$REMOTE" fi status=$? - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" - fi + save_backup ;; meld|vimdiff) touch "$BACKUP" $merge_tool -- "$LOCAL" "$path" "$REMOTE" - if test "$path" -nt "$BACKUP" ; then - status=0; - else - while true; do - echo "$path seems unchanged." - printf "Was the merge successful? [y/n] " - read answer < /dev/tty - case "$answer" in - y*|Y*) status=0; break ;; - n*|N*) status=1; break ;; - esac - done - fi - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" - fi + check_unchanged + save_backup ;; xxdiff) touch "$BACKUP" @@ -217,22 +227,8 @@ merge_file () { -R 'Accel.SearchForward: "Ctrl-G"' \ --merged-file "$path" -- "$LOCAL" "$REMOTE" fi - if test "$path" -nt "$BACKUP" ; then - status=0; - else - while true; do - echo "$path seems unchanged." - printf "Was the merge successful? [y/n] " - read answer < /dev/tty - case "$answer" in - y*|Y*) status=0; break ;; - n*|N*) status=1; break ;; - esac - done - fi - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" - fi + check_unchanged + save_backup ;; emerge) if base_present ; then @@ -241,9 +237,7 @@ merge_file () { emacs -f emerge-files-command "$LOCAL" "$REMOTE" "$path" fi status=$? - if test "$status" -eq 0; then - mv -- "$BACKUP" "$path.orig" - fi + save_backup ;; esac if test "$status" -ne 0; then From b7b36f92fd096d1ff0d4cccd8980c93c3bff4fa8 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 09:46:31 -0400 Subject: [PATCH 107/130] mergetool: Remove spurious error message if merge.tool config option not set Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 1355fcb19f..c1fde41a08 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -280,7 +280,7 @@ done if test -z "$merge_tool"; then merge_tool=`git-config merge.tool` case "$merge_tool" in - kdiff3 | tkdiff | xxdiff | meld | emerge | vimdiff) + kdiff3 | tkdiff | xxdiff | meld | emerge | vimdiff | "") ;; # happy *) echo >&2 "git config option merge.tool set to unknown tool: $merge_tool" From 5a174f1a2ee338172d1ca1dab4e30f5968535f2d Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 09:48:31 -0400 Subject: [PATCH 108/130] mergetool: Fix abort command when resolving symlinks and deleted files Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index c1fde41a08..9b736507be 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -71,13 +71,13 @@ resolve_symlink_merge () { cleanup_temp_files --save-backup return ;; - [rR]*) + [rR]*) git-checkout-index -f --stage=3 -- "$path" git-add -- "$path" cleanup_temp_files --save-backup return ;; - [qQ]*) + [aA]*) exit 1 ;; esac @@ -94,12 +94,12 @@ resolve_deleted_merge () { cleanup_temp_files --save-backup return ;; - [dD]*) + [dD]*) git-rm -- "$path" cleanup_temp_files return ;; - [qQ]*) + [aA]*) exit 1 ;; esac From 365cf979c48a52eec65f29a02a973753418396f4 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 10:03:17 -0400 Subject: [PATCH 109/130] mergetool: Add support for Apple Mac OS X's opendiff command Signed-off-by: Arjen Laarhoven Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 9b736507be..58794cad49 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -230,6 +230,16 @@ merge_file () { check_unchanged save_backup ;; + opendiff) + touch "$BACKUP" + if base_present; then + opendiff "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$path" | cat + else + opendiff "$LOCAL" "$REMOTE" -merge "$path" | cat + fi + check_unchanged + save_backup + ;; emerge) if base_present ; then emacs -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$path" @@ -280,7 +290,7 @@ done if test -z "$merge_tool"; then merge_tool=`git-config merge.tool` case "$merge_tool" in - kdiff3 | tkdiff | xxdiff | meld | emerge | vimdiff | "") + kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | "") ;; # happy *) echo >&2 "git config option merge.tool set to unknown tool: $merge_tool" @@ -299,6 +309,8 @@ if test -z "$merge_tool" ; then merge_tool=xxdiff elif type meld >/dev/null 2>&1 && test -n "$DISPLAY"; then merge_tool=meld + elif type opendiff >/dev/null 2>&1; then + merge_tool=opendiff elif type emacs >/dev/null 2>&1; then merge_tool=emerge elif type vimdiff >/dev/null 2>&1; then @@ -310,7 +322,7 @@ if test -z "$merge_tool" ; then fi case "$merge_tool" in - kdiff3|tkdiff|meld|xxdiff|vimdiff) + kdiff3|tkdiff|meld|xxdiff|vimdiff|opendiff) if ! type "$merge_tool" > /dev/null 2>&1; then echo "The merge tool $merge_tool is not available" exit 1 From 1346c9996350e96c7b38a57ede5d503821d84fe3 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 10:05:02 -0400 Subject: [PATCH 110/130] mergetool: Make git-rm quiet when resolving a deleted file conflict Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 58794cad49..7a2b9b9f02 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -95,7 +95,7 @@ resolve_deleted_merge () { return ;; [dD]*) - git-rm -- "$path" + git-rm -- "$path" > /dev/null cleanup_temp_files return ;; From 27090aa1eabdc44553a0d8a51ff4ab9543c64c65 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Thu, 29 Mar 2007 11:39:46 -0400 Subject: [PATCH 111/130] mergetool: Clean up description of files and prompts for merge resolutions This fixes complaints from Junio for how messages and prompts are printed when resolving symlink and deleted file merges. Signed-off-by: "Theodore Ts'o" --- git-mergetool.sh | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/git-mergetool.sh b/git-mergetool.sh index 7a2b9b9f02..e62351bcba 100755 --- a/git-mergetool.sh +++ b/git-mergetool.sh @@ -44,25 +44,24 @@ describe_file () { branch="$2" file="$3" - printf " " + printf " {%s}: " "$branch" if test -z "$mode"; then - printf "'%s' was deleted" "$path" + echo "deleted" elif is_symlink "$mode" ; then - printf "'%s' is a symlink containing '%s'" "$path" "$file" + echo "a symbolic link -> '$(cat "$file")'" else if base_present; then - printf "'%s' was created" "$path" + echo "modified" else - printf "'%s' was modified" "$path" + echo "created" fi fi - echo " in the $branch branch" } resolve_symlink_merge () { while true; do - printf "Use (r)emote or (l)ocal, or (a)bort? " + printf "Use (l)ocal or (r)emote, or (a)bort? " read ans case "$ans" in [lL]*) @@ -86,10 +85,14 @@ resolve_symlink_merge () { resolve_deleted_merge () { while true; do - printf "Use (m)odified or (d)eleted file, or (a)bort? " + if base_present; then + printf "Use (m)odified or (d)eleted file, or (a)bort? " + else + printf "Use (c)reated or (d)eleted file, or (a)bort? " + fi read ans case "$ans" in - [mM]*) + [mMcC]*) git-add -- "$path" cleanup_temp_files --save-backup return @@ -164,7 +167,7 @@ merge_file () { remote_present && git cat-file blob ":3:$path" > "$REMOTE" 2>/dev/null if test -z "$local_mode" -o -z "$remote_mode"; then - echo "Deleted merge conflict for $path:" + echo "Deleted merge conflict for '$path':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" resolve_deleted_merge @@ -172,14 +175,14 @@ merge_file () { fi if is_symlink "$local_mode" || is_symlink "$remote_mode"; then - echo "Symlink merge conflict for $path:" + echo "Symbolic link merge conflict for '$path':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" resolve_symlink_merge return fi - echo "Normal merge conflict for $path:" + echo "Normal merge conflict for '$path':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" printf "Hit return to start merge resolution tool (%s): " "$merge_tool" From 6f01e6b37008e45efb2b17a027f045600a011e93 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Thu, 29 Mar 2007 09:42:35 +0200 Subject: [PATCH 112/130] Bisect: Improve error message in "bisect_next_check". So we can remove the specific message in "bisect_run". Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- git-bisect.sh | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/git-bisect.sh b/git-bisect.sh index 57d6754d34..11313a7949 100755 --- a/git-bisect.sh +++ b/git-bisect.sh @@ -123,7 +123,15 @@ bisect_next_check() { case "$next_ok,$1" in no,) false ;; no,fail) - echo >&2 'You need to give me at least one good and one bad revisions.' + THEN='' + test -d "$GIT_DIR/refs/bisect" || { + echo >&2 'You need to start by "git bisect start".' + THEN='then ' + } + echo >&2 'You '$THEN'need to give me at least one good' \ + 'and one bad revisions.' + echo >&2 '(You can use "git bisect bad" and' \ + '"git bisect good" for that.)' exit 1 ;; *) true ;; @@ -223,12 +231,6 @@ bisect_replay () { } bisect_run () { - # Check that we have everything to run correctly. - test -d "$GIT_DIR/refs/bisect" || { - echo >&2 'You need to start by "git bisect start".' - echo >&2 'And then by "git bisect bad" and "git bisect good".' - exit 1 - } bisect_next_check fail while true From b275a0c9e742e4bbfed9794b1e477000440eaf6a Mon Sep 17 00:00:00 2001 From: Francis Daly Date: Thu, 29 Mar 2007 22:38:20 +0100 Subject: [PATCH 113/130] git-quiltimport /bin/sh-ism fix Bryan Wu reported /usr/local/bin/git-quiltimport: 114: Syntax error: Missing '))' Most bourne-ish shells I have here accept x=$((echo x)|cat) but all bourne-ish shells I have here accept x=$( (echo x)|cat) because $(( might mean arithmetic expansion. Signed-off-by: Francis Daly Signed-off-by: Junio C Hamano --- git-quiltimport.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-quiltimport.sh b/git-quiltimport.sh index 08ac9bb729..edccd82755 100755 --- a/git-quiltimport.sh +++ b/git-quiltimport.sh @@ -115,7 +115,7 @@ for patch_name in $(cat "$QUILT_PATCHES/series" | grep -v '^#'); do if [ -z "$dry_run" ] ; then git-apply --index -C1 "$tmp_patch" && tree=$(git-write-tree) && - commit=$((echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) && + commit=$( (echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) && git-update-ref -m "quiltimport: $patch_name" HEAD $commit || exit 4 fi done From a208362fad4ebfd341f4c57fee795302a4b1f42c Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 30 Mar 2007 00:56:36 -0700 Subject: [PATCH 114/130] Update draft release notes for 1.5.1 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.1.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/RelNotes-1.5.1.txt b/Documentation/RelNotes-1.5.1.txt index 8461fb4371..f48d816c7b 100644 --- a/Documentation/RelNotes-1.5.1.txt +++ b/Documentation/RelNotes-1.5.1.txt @@ -86,11 +86,16 @@ Updates since v1.5.0 to run after each revision is checked out to determine if it is good or bad, to automate the bisection process. + - "git log" family learned a new traversal option --first-parent, + which does what the name suggests. + * Updated behaviour of existing commands. - "git fsck" does not barf on corrupt loose objects. + - "git rm" does not remove newly added files without -f. + - "git archimport" allows remapping when coming up with git branch names from arch names. @@ -183,7 +188,7 @@ Updates since v1.5.0 -- exec >/var/tmp/1 -O=v1.5.1-rc1-63-g12d6697 +O=v1.5.1-rc3-18-ge881192 echo O=`git describe master` git shortlog --no-merges $O..master ^maint From aa453216d1b3e49e7f6f98441fa56946ddcd6a20 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 30 Mar 2007 01:03:09 -0700 Subject: [PATCH 115/130] Do not bother documenting fetch--tool Signed-off-by: Junio C Hamano --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 960f98e801..b159ffd0ae 100644 --- a/Makefile +++ b/Makefile @@ -991,7 +991,7 @@ check-docs:: git-merge-octopus | git-merge-ours | git-merge-recursive | \ git-merge-resolve | git-merge-stupid | \ git-add--interactive | git-fsck-objects | git-init-db | \ - git-repo-config | \ + git-repo-config | git-fetch--tool | \ git-ssh-pull | git-ssh-push ) continue ;; \ esac ; \ test -f "Documentation/$$v.txt" || \ From 5ae917acdf40444945271e5e014cda37e202504e Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Fri, 30 Mar 2007 23:41:26 +0200 Subject: [PATCH 116/130] gitweb: Support comparing blobs (files) with different names Fix the bug that caused "blobdiff" view called with new style URI for a rename with change diff to be show as new (added) file diff. New style URI for "blobdiff" for rename means with $hash_base ('hb') and $hash_parent_base ('hpb') paramaters denoting tree-ish (usually commit) of a blobs being compared, together with both $file_name ('f') and $file_parent ('fp') parameters. It is done by adding $file_parent ('fp') to the path limiter, meaning that diff command becomes: git diff-tree [options] hpb hb -- fp f Other option would be finding hash of a blob using git_get_hash_by_path subroutine and comparing blobs using git-diff, or using extended SHA-1 syntax and compare blobs using git-diff: git diff [options] hpb:fp hp:f Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 3348583227..3786955fca 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -3885,7 +3885,7 @@ sub git_blobdiff { # read raw output open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, $hash_parent_base, $hash_base, - "--", $file_name + "--", (defined $file_parent ? $file_parent : ()), $file_name or die_error(undef, "Open git-diff-tree failed"); @difftree = map { chomp; $_ } <$fd>; close $fd @@ -3935,7 +3935,7 @@ sub git_blobdiff { # open patch output open $fd, "-|", git_cmd(), "diff-tree", '-r', @diff_opts, '-p', $hash_parent_base, $hash_base, - "--", $file_name + "--", (defined $file_parent ? $file_parent : ()), $file_name or die_error(undef, "Open git-diff-tree failed"); } From 86747c132b87fc97bbb134baaffe9ecc12c5a90d Mon Sep 17 00:00:00 2001 From: Don Zickus Date: Fri, 30 Mar 2007 12:18:45 -0400 Subject: [PATCH 117/130] git-mailinfo fixes for patch munging Don't translate the patch to UTF-8, instead preserve the data as is. This also reverts a test case that was included in the original patch series. Also allow overwriting the authorship and title information we gather from RFC2822 mail headers with additional in-body headers, which was pointed out by Linus. Signed-off-by: Don Zickus Signed-off-by: Junio C Hamano --- builtin-mailinfo.c | 23 ++++++++++++----------- t/t5100/patch0005 | 2 +- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/builtin-mailinfo.c b/builtin-mailinfo.c index d94578cb4a..c95e477e83 100644 --- a/builtin-mailinfo.c +++ b/builtin-mailinfo.c @@ -294,14 +294,14 @@ static char *header[MAX_HDR_PARSED] = { "From","Subject","Date", }; -static int check_header(char *line, char **hdr_data) +static int check_header(char *line, char **hdr_data, int overwrite) { int i; /* search for the interesting parts */ for (i = 0; header[i]; i++) { int len = strlen(header[i]); - if (!hdr_data[i] && + if ((!hdr_data[i] || overwrite) && !strncasecmp(line, header[i], len) && line[len] == ':' && isspace(line[len + 1])) { /* Unwrap inline B and Q encoding, and optionally @@ -614,6 +614,7 @@ static int find_boundary(void) static int handle_boundary(void) { + char newline[]="\n"; again: if (!memcmp(line+content_top->boundary_len, "--", 2)) { /* we hit an end boundary */ @@ -628,7 +629,7 @@ again: "can't recover\n"); exit(1); } - handle_filter("\n"); + handle_filter(newline); /* skip to the next boundary */ if (!find_boundary()) @@ -643,7 +644,7 @@ again: /* slurp in this section's info */ while (read_one_header_line(line, sizeof(line), fin)) - check_header(line, p_hdr_data); + check_header(line, p_hdr_data, 0); /* eat the blank line after section info */ return (fgets(line, sizeof(line), fin) != NULL); @@ -699,10 +700,14 @@ static int handle_commit_msg(char *line) if (!*cp) return 0; } - if ((still_looking = check_header(cp, s_hdr_data)) != 0) + if ((still_looking = check_header(cp, s_hdr_data, 0)) != 0) return 0; } + /* normalize the log message to UTF-8. */ + if (metainfo_charset) + convert_to_utf8(line, charset); + if (patchbreak(line)) { fclose(cmitmsg); cmitmsg = NULL; @@ -767,12 +772,8 @@ static void handle_body(void) return; } - /* Unwrap transfer encoding and optionally - * normalize the log message to UTF-8. - */ + /* Unwrap transfer encoding */ decode_transfer_encoding(line); - if (metainfo_charset) - convert_to_utf8(line, charset); switch (transfer_encoding) { case TE_BASE64: @@ -875,7 +876,7 @@ int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, /* process the email header */ while (read_one_header_line(line, sizeof(line), fin)) - check_header(line, p_hdr_data); + check_header(line, p_hdr_data, 1); handle_body(); handle_info(); diff --git a/t/t5100/patch0005 b/t/t5100/patch0005 index e7d6f66608..7d24b24af8 100644 --- a/t/t5100/patch0005 +++ b/t/t5100/patch0005 @@ -61,7 +61,7 @@ diff --git a/git-cvsimport-script b/git-cvsimport-script push(@old,$fn); -- -David KÃ¥gedal +David Kågedal - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@vger.kernel.org From 46efd2d93ce39fd5c1a91f0a2f918f2d8bbfdf92 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Fri, 30 Mar 2007 19:07:05 -0400 Subject: [PATCH 118/130] Rename warn() to warning() to fix symbol conflicts on BSD and Mac OS This fixes a problem reported by Randal Schwartz: >I finally tracked down all the (albeit inconsequential) errors I was getting >on both OpenBSD and OSX. It's the warn() function in usage.c. There's >warn(3) in BSD-style distros. It'd take a "great rename" to change it, but if >someone with better C skills than I have could do that, my linker and I would >appreciate it. It was annoying to me, too, when I was doing some mergetool testing on Mac OS X, so here's a fix. Signed-off-by: "Theodore Ts'o" Cc: "Randal L. Schwartz" Signed-off-by: Junio C Hamano --- builtin-bundle.c | 4 ++-- fast-import.c | 2 +- git-compat-util.h | 2 +- revision.c | 2 +- usage.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/builtin-bundle.c b/builtin-bundle.c index 0a9b73867f..d1635a0a6b 100644 --- a/builtin-bundle.c +++ b/builtin-bundle.c @@ -87,7 +87,7 @@ static int read_header(const char *path, struct bundle_header *header) { if (buffer[len - 1] == '\n') buffer[len - 1] = '\0'; if (get_sha1_hex(buffer + offset, sha1)) { - warn("unrecognized header: %s", buffer); + warning("unrecognized header: %s", buffer); continue; } delim = buffer[40 + offset]; @@ -268,7 +268,7 @@ static int create_bundle(struct bundle_header *header, const char *path, * from getting output. */ if (!(e->item->flags & SHOWN)) { - warn("ref '%s' is excluded by the rev-list options", + warning("ref '%s' is excluded by the rev-list options", e->name); continue; } diff --git a/fast-import.c b/fast-import.c index bea12151c2..cdd629d6bc 100644 --- a/fast-import.c +++ b/fast-import.c @@ -1312,7 +1312,7 @@ static int update_branch(struct branch *b) if (!in_merge_bases(old_cmit, &new_cmit, 1)) { unlock_ref(lock); - warn("Not updating %s" + warning("Not updating %s" " (new tip %s does not contain %s)", b->name, sha1_to_hex(b->sha1), sha1_to_hex(old_sha1)); return -1; diff --git a/git-compat-util.h b/git-compat-util.h index 7534db1267..139fc19108 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -87,7 +87,7 @@ 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 void warn(const char *err, ...) __attribute__((format (printf, 1, 2))); +extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2))); extern void set_usage_routine(void (*routine)(const char *err) NORETURN); extern void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN); diff --git a/revision.c b/revision.c index f23c1d5226..486393cb08 100644 --- a/revision.c +++ b/revision.c @@ -486,7 +486,7 @@ static void handle_one_reflog_commit(unsigned char *sha1, void *cb_data) add_pending_object(cb->all_revs, o, ""); } else if (!cb->warned_bad_reflog) { - warn("reflog of '%s' references pruned commits", + warning("reflog of '%s' references pruned commits", cb->name_for_errormsg); cb->warned_bad_reflog = 1; } diff --git a/usage.c b/usage.c index 4dc5c77633..f5e652cc76 100644 --- a/usage.c +++ b/usage.c @@ -86,7 +86,7 @@ int error(const char *err, ...) return -1; } -void warn(const char *warn, ...) +void warning(const char *warn, ...) { va_list params; From a6a15a9958cbd77e7181c2110e1e2568a808a204 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Fri, 30 Mar 2007 17:54:48 -0700 Subject: [PATCH 119/130] git-svn: avoid respewing similar error messages for missing paths We ignore errors if the path we're tracking did not exist for a particular revision range, but we still print out warnings telling the user about that. As pointed out by Seth Falcon, this amounts to a lot of warnings that could confuse and worry users. I'm not entirely comfortable completely silencing the warnings, but showing one warning per path that we track should be reasonable. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index e0a48c2a8b..278f45d6d0 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -2840,8 +2840,7 @@ package Git::SVN::Ra; use vars qw/@ISA $config_dir $_log_window_size/; use strict; use warnings; -my ($can_do_switch); -my $RA; +my ($can_do_switch, %ignored_err, $RA); BEGIN { # enforce temporary pool usage for some simple functions @@ -3213,9 +3212,16 @@ sub skip_unknown_revs { # 175007 - http(s):// (this repo required authorization, too...) # More codes may be discovered later... if ($errno == 175007 || $errno == 175002 || $errno == 160013) { - warn "W: Ignoring error from SVN, path probably ", - "does not exist: ($errno): ", - $err->expanded_message,"\n"; + my $err_key = $err->expanded_message; + # revision numbers change every time, filter them out + $err_key =~ s/\d+/\0/g; + $err_key = "$errno\0$err_key"; + unless ($ignored_err{$err_key}) { + warn "W: Ignoring error from SVN, path probably ", + "does not exist: ($errno): ", + $err->expanded_message,"\n"; + $ignored_err{$err_key} = 1; + } return; } die "Error from SVN, ($errno): ", $err->expanded_message,"\n"; From 4557e0de5b7ef9d25cc7618ca37ae5f1acf82806 Mon Sep 17 00:00:00 2001 From: Andy Parkins Date: Fri, 30 Mar 2007 19:16:26 +0000 Subject: [PATCH 120/130] Reimplement emailing part of hooks--update in contrib/hooks/post-receive-email The update hook is no longer the correct place to generate emails; there is now the hooks/post-receive script which is run automatically after a ref has been updated. This patch is to make use of that new location, and to address some faults in the old update hook. The primary problem in the conversion was that in the update hook, the ref has not actually been changed, but is about to be. In the post-receive hook the ref has already been updated. That meant that where we previously had lines like: git rev-list --not --all would now give the wrong list because "--all" in the post-receive hook includes the ref that we are making the email for. This made it more difficult to show only the new revisions added by this update. The solution is not pretty; however it does work and doesn't need any changes to git-rev-list itself. It also fixes (more accurately: reduces the likelihood of) a nasty race when another update occurs while this script is running. The solution, in short, looks like this (see the source code for a longer explanation) git rev-parse --not --all | grep -v $(git rev-parse $refname) | git rev-list --pretty --stdin $oldrev..$newrev This uses git-rev-parse followed by grep to filter out the revision of the ref in question before it gets to rev-list and inhibits the output of itself. By using $(git rev-parse $revname) rather than $newrev as the filter, it also takes care of the situation where another update to the same ref has been made since $refname was $newrev. The second problem that is addressed is that of tags inhibiting the correct output of an update email. Consider this, with somebranch and sometag pointing at the same revision: git push origin somebranch git push origin sometag That would work fine; the push of the branch would generate an email containing all the new commits introduced by the update, then the push of the tag would generate the shortlog formatted tag email. Now consider: git push origin sometag git push origin somebranch When some branch comes to run its "--not --all" line, it will find sometag, and filter those commits from the email - leaving nothing. That meant that those commits would not show (in full) on any email. The fix is to not use "--all", and instead use "--branches" in the git-rev-parse command. Other changes * Lose the monstrous one-giant-script layout and put things in easy to digest functions. This makes it much easier to find the place you need to change if you wanted to customise the output. I've also tried to write more verbose comments for the same reason. The hook script is big, mainly because of all the different cases that it has to handle, so being easy to navigate is important. * All uses of "git-command" changed to "git command", to cope better if a user decided not to install all the hard links to git; * Cleaned up some of the English in the email * The fact that the receive hook makes the ref available also allows me to use Shawn Pearce's fantastic suggestion that an annotated tag can be parsed with git-for-each-ref. This removes the potentially non-portable use of "<<<" heredocs and the nasty messing around with "date" to convert numbers of seconds UTC to a real date * Deletions are now caught and notified (briefly) * To help with debugging, I've retained the command line mode from the update hook; but made it so that the output is not emailed, it's just printed to the screen. This could then be redirected if the user wanted * Removed the "Hello" from the beginning of the email - it's just noise, and no one seriously has their day made happier by "friendly" programs * The fact that it doesn't rely on repository state as an indicator any more means that it's far more stable in its output; hopefully the same arguments will always generate the same email - even if the repository changes in the future. This means you can easily recreate an email should you want to. * Included Jim Meyering's envelope sender option for the sendmail call * The hook is now so big that it was inappropriate to copy it to every repository by keeping it in the templates directory. Instead, I've put a comment saying to look in contrib/hooks, and given an example of calling the script from that template hook. The advantage of calling the script residing at some fixed location is that if a future package of git included a bug fixed version of the script, that would be picked up automatically, and the user would not have to notice and manually copy the new hook to every repository that uses it. Signed-off-by: Andy Parkins Signed-off-by: Junio C Hamano --- contrib/hooks/post-receieve-email | 588 ++++++++++++++++++++++++++++++ templates/hooks--post-receive | 17 + 2 files changed, 605 insertions(+) create mode 100644 contrib/hooks/post-receieve-email create mode 100644 templates/hooks--post-receive diff --git a/contrib/hooks/post-receieve-email b/contrib/hooks/post-receieve-email new file mode 100644 index 0000000000..65160153ee --- /dev/null +++ b/contrib/hooks/post-receieve-email @@ -0,0 +1,588 @@ +#!/bin/sh +# +# Copyright (c) 2007 Andy Parkins +# +# An example hook script to mail out commit update information. This hook sends emails +# listing new revisions to the repository introduced by the change being reported. The +# rule is that (for branch updates) each commit will appear on one email and one email +# only. +# +# This hook is stored in the contrib/hooks directory. Your distribution will have put +# this somewhere standard. You should make this script executable then link to it in +# the repository you would like to use it in. For example, on debian the hook is stored +# in /usr/share/doc/git-core/contrib/hooks/post-receive-email: +# +# chmod a+x post-receive-email +# cd /path/to/your/repository.git +# ln -sf /usr/share/doc/git-core/contrib/hooks/post-receive-email hooks/post-receive +# +# This hook script assumes it is enabled on the central repository of a project, with +# all users pushing only to it and not between each other. It will still work if you +# don't operate in that style, but it would become possible for the email to be from +# someone other than the person doing the push. +# +# Config +# ------ +# hooks.mailinglist +# This is the list that all pushes will go to; leave it blank to not send +# emails for every ref update. +# hooks.announcelist +# This is the list that all pushes of annotated tags will go to. Leave it +# blank to default to the mailinglist field. The announce emails lists the +# short log summary of the changes since the last annotated tag. +# hook.envelopesender +# If set then the -f option is passed to sendmail to allow the envelope sender +# address to be set +# +# Notes +# ----- +# All emails have their subjects prefixed with "[SCM]" to aid filtering. +# All emails include the headers "X-Git-Refname", "X-Git-Oldrev", +# "X-Git-Newrev", and "X-Git-Reftype" to enable fine tuned filtering and +# give information for debugging. +# + +# ---------------------------- Functions + +# +# Top level email generation function. This decides what type of update +# this is and calls the appropriate body-generation routine after outputting +# the common header +# +# Note this function doesn't actually generate any email output, that is taken +# care of by the functions it calls: +# - generate_email_header +# - generate_create_XXXX_email +# - generate_update_XXXX_email +# - generate_delete_XXXX_email +# - generate_email_footer +# +generate_email() +{ + # --- Arguments + oldrev=$(git rev-parse $1) + newrev=$(git rev-parse $2) + refname="$3" + + # --- Interpret + # 0000->1234 (create) + # 1234->2345 (update) + # 2345->0000 (delete) + if expr "$oldrev" : '0*$' >/dev/null + then + change_type="create" + else + if expr "$newrev" : '0*$' >/dev/null + then + change_type="delete" + else + change_type="update" + fi + fi + + # --- Get the revision types + newrev_type=$(git cat-file -t $newrev 2> /dev/null) + oldrev_type=$(git cat-file -t "$oldrev" 2> /dev/null) + case "$change_type" in + create|update) + rev="$newrev" + rev_type="$newrev_type" + ;; + delete) + rev="$oldrev" + rev_type="$oldrev_type" + ;; + esac + + # The revision type tells us what type the commit is, combined with + # the location of the ref we can decide between + # - working branch + # - tracking branch + # - unannoted tag + # - annotated tag + case "$refname","$rev_type" in + refs/tags/*,commit) + # un-annotated tag + refname_type="tag" + short_refname=${refname##refs/tags/} + ;; + refs/tags/*,tag) + # annotated tag + refname_type="annotated tag" + short_refname=${refname##refs/tags/} + # change recipients + if [ -n "$announcerecipients" ]; then + recipients="$announcerecipients" + fi + ;; + refs/heads/*,commit) + # branch + refname_type="branch" + short_refname=${refname##refs/heads/} + ;; + refs/remotes/*,commit) + # tracking branch + refname_type="tracking branch" + short_refname=${refname##refs/remotes/} + echo >&2 "*** Push-update of tracking branch, $refname" + echo >&2 "*** - no email generated." + exit 0 + ;; + *) + # Anything else (is there anything else?) + echo >&2 "*** Unknown type of update to $refname ($rev_type)" + echo >&2 "*** - no email generated" + exit 1 + ;; + esac + + # Check if we've got anyone to send to + if [ -z "$recipients" ]; then + echo >&2 "*** hooks.recipients is not set so no email will be sent" + echo >&2 "*** for $refname update $oldrev->$newrev" + exit 0 + fi + + # Email parameters + # The committer will be obtained from the latest existing rev; so + # for a deletion it will be the oldrev, for the others, then newrev + committer=$(git show --pretty=full -s $rev | sed -ne "s/^Commit: //p" | + sed -ne 's/\(.*\) /dev/null) + if [ -z "$describe" ]; then + describe=$rev + fi + + generate_email_header + + # Call the correct body generation function + fn_name=general + case "$refname_type" in + "tracking branch"|branch) + fn_name=branch + ;; + "annotated tag") + fn_name=atag + ;; + esac + generate_${change_type}_${fn_name}_email + + generate_email_footer +} + +generate_email_header() +{ + # --- Email (all stdout will be the email) + # Generate header + cat <<-EOF + From: $committer + To: $recipients + Subject: ${EMAILPREFIX}$projectdesc $refname_type, $short_refname, ${change_type}d. $describe + X-Git-Refname: $refname + X-Git-Reftype: $refname_type + X-Git-Oldrev: $oldrev + X-Git-Newrev: $newrev + + This is an automated email from the git hooks/post-receive script. It was + generated because a ref change was pushed to the repository containing + the project "$projectdesc". + + The $refname_type, $short_refname has been ${change_type}d + EOF +} + +generate_email_footer() +{ + cat <<-EOF + + + hooks/post-receive + -- + $projectdesc + EOF +} + +# --------------- Branches + +# +# Called for the creation of a branch +# +generate_create_branch_email() +{ + # This is a new branch and so oldrev is not valid + echo " at $newrev ($newrev_type)" + echo "" + + echo $LOGBEGIN + # This shows all log entries that are not already covered by + # another ref - i.e. commits that are now accessible from this + # ref that were previously not accessible (see generate_update_branch_email + # for the explanation of this command) + git rev-parse --not --branches | grep -v $(git rev-parse $refname) | + git rev-list --pretty --stdin $newrev + echo $LOGEND +} + +# +# Called for the change of a pre-existing branch +# +generate_update_branch_email() +{ + # Consider this: + # 1 --- 2 --- O --- X --- 3 --- 4 --- N + # + # O is $oldrev for $refname + # N is $newrev for $refname + # X is a revision pointed to by some other ref, for which we may + # assume that an email has already been generated. + # In this case we want to issue an email containing only revisions + # 3, 4, and N. Given (almost) by + # + # git-rev-list N ^O --not --all + # + # The reason for the "almost", is that the "--not --all" will take + # precedence over the "N", and effectively will translate to + # + # git-rev-list N ^O ^X ^N + # + # So, we need to build up the list more carefully. git-rev-parse will + # generate a list of revs that may be fed into git-rev-list. We can get + # it to make the "--not --all" part and then filter out the "^N" with: + # + # git-rev-parse --not --all | grep -v N + # + # Then, using the --stdin switch to git-rev-list we have effectively + # manufactured + # + # git-rev-list N ^O ^X + # + # This leaves a problem when someone else updates the repository + # while this script is running. Their new value of the ref we're working + # on would be included in the "--not --all" output; and as our $newrev + # would be an ancestor of that commit, it would exclude all of our + # commits. What we really want is to exclude the current value of + # $refname from the --not list, rather than N itself. So: + # + # git-rev-parse --not --all | grep -v $(git-rev-parse $refname) + # + # Get's us to something pretty safe (apart from the small time between + # refname being read, and git-rev-parse running - for that, I give up) + # + # + # Next problem, consider this: + # * --- B --- * --- O ($oldrev) + # \ + # * --- X --- * --- N ($newrev) + # + # That is to say, there is no guarantee that oldrev is a strict subset of + # newrev (it would have required a --force, but that's allowed). So, we + # can't simply say rev-list $oldrev..$newrev. Instead we find the common + # base of the two revs and list from there. + # + # As above, we need to take into account the presence of X; if another + # branch is already in the repository and points at some of the revisions + # that we are about to output - we don't want them. The solution is as + # before: git-rev-parse output filtered. + # + # Finally, tags: + # 1 --- 2 --- O --- T --- 3 --- 4 --- N + # + # Tags pushed into the repository generate nice shortlog emails that + # summarise the commits between them and the previous tag. However, + # those emails don't include the full commit messages that we output + # for a branch update. Therefore we still want to output revisions + # that have been output on a tag email. + # + # Luckily, git-rev-parse includes just the tool. Instead of using "--all" + # we use "--branches"; this has the added benefit that "remotes/" will + # be ignored as well. + + # List all of the revisions that were removed by this update, in a fast forward + # update, this list will be empty, because rev-list O ^N is empty. For a non + # fast forward, O ^N is the list of removed revisions + fastforward="" + rev="" + for rev in $(git rev-list $newrev..$oldrev) + do + revtype=$(git cat-file -t "$rev") + echo " discards $rev ($revtype)" + done + if [ -z "$rev" ]; then + fast_forward=1 + fi + + # List all the revisions from baserev to newrev in a kind of + # "table-of-contents"; note this list can include revisions that have + # already had notification emails and is present to show the full detail + # of the change from rolling back the old revision to the base revision and + # then forward to the new revision + for rev in $(git rev-list $oldrev..$newrev) + do + revtype=$(git cat-file -t "$rev") + echo " via $rev ($revtype)" + done + + if [ -z "$fastforward" ]; then + echo " from $oldrev ($oldrev_type)" + else + echo "" + echo "This update added new revisions after undoing old revisions. That is to" + echo "say, the old revision is not a strict subset of the new revision. This" + echo "situation occurs when you --force push a change and generate a" + echo "repository containing something like this:" + echo "" + echo " * -- * -- B -- O -- O -- O ($oldrev)" + echo " \\" + echo " N -- N -- N ($newrev)" + echo "" + echo "When this happens we assume that you've already had alert emails for all" + echo "of the O revisions, and so we here report only the revisions in the N" + echo "branch from the common base, B." + fi + + echo "" + echo "Those revisions listed above that are new to this repository have" + echo "not appeared on any other notification email; so we list those" + echo "revisions in full, below." + + echo "" + echo $LOGBEGIN + git rev-parse --not --branches | grep -v $(git rev-parse $refname) | + git rev-list --pretty --stdin $oldrev..$newrev + + # XXX: Need a way of detecting whether git rev-list actually outputted + # anything, so that we can issue a "no new revisions added by this + # update" message + + echo $LOGEND + + # The diffstat is shown from the old revision to the new revision. This + # is to show the truth of what happened in this change. There's no point + # showing the stat from the base to the new revision because the base + # is effectively a random revision at this point - the user will be + # interested in what this revision changed - including the undoing of + # previous revisions in the case of non-fast forward updates. + echo "" + echo "Summary of changes:" + git diff-tree --stat --summary --find-copies-harder $oldrev..$newrev +} + +# +# Called for the deletion of a branch +# +generate_delete_branch_email() +{ + echo " was $oldrev" + echo "" + echo $LOGEND + git show -s --pretty=oneline $oldrev + echo $LOGEND +} + +# --------------- Annotated tags + +# +# Called for the creation of an annotated tag +# +generate_create_atag_email() +{ + echo " at $newrev ($newrev_type)" + + generate_atag_email +} + +# +# Called for the update of an annotated tag (this is probably a rare event +# and may not even be allowed) +# +generate_update_atag_email() +{ + echo " to $newrev ($newrev_type)" + echo " from $oldrev (which is now obsolete)" + + generate_atag_email +} + +# +# Called when an annotated tag is created or changed +# +generate_atag_email() +{ + # Use git-for-each-ref to pull out the individual fields from the tag + eval $(git for-each-ref --shell --format=' + tagobject=%(*objectname) + tagtype=%(*objecttype) + tagger=%(taggername) + tagged=%(taggerdate)' $refname + ) + + echo " tagging $tagobject ($tagtype)" + case "$tagtype" in + commit) + # If the tagged object is a commit, then we assume this is a + # release, and so we calculate which tag this tag is replacing + prevtag=$(git describe --abbrev=0 $newrev^ 2>/dev/null) + + if [ -n "$prevtag" ]; then + echo " replaces $prevtag" + fi + ;; + *) + echo " length $(git cat-file -s $tagobject) bytes" + ;; + esac + echo " tagged by $tagger" + echo " on $tagged" + + echo "" + echo $LOGBEGIN + + # Show the content of the tag message; this might contain a change log + # or release notes so is worth displaying. + git cat-file tag $newrev | sed -e '1,/^$/d' + + echo "" + case "$tagtype" in + commit) + # Only commit tags make sense to have rev-list operations performed + # on them + if [ -n "$prevtag" ]; then + # Show changes since the previous release + git rev-list --pretty=short "$prevtag..$newrev" | git shortlog + else + # No previous tag, show all the changes since time began + git rev-list --pretty=short $newrev | git shortlog + fi + ;; + *) + # XXX: Is there anything useful we can do for non-commit objects? + ;; + esac + + echo $LOGEND +} + +# +# Called for the deletion of an annotated tag +# +generate_delete_atag_email() +{ + echo " was $oldrev" + echo "" + echo $LOGEND + git show -s --pretty=oneline $oldrev + echo $LOGEND +} + +# --------------- General references + +# +# Called when any other type of reference is created (most likely a +# non-annotated tag) +# +generate_create_general_email() +{ + echo " at $newrev ($newrev_type)" + + generate_general_email +} + +# +# Called when any other type of reference is updated (most likely a +# non-annotated tag) +# +generate_update_general_email() +{ + echo " to $newrev ($newrev_type)" + echo " from $oldrev" + + generate_general_email +} + +# +# Called for creation or update of any other type of reference +# +generate_general_email() +{ + # Unannotated tags are more about marking a point than releasing a version; + # therefore we don't do the shortlog summary that we do for annotated tags + # above - we simply show that the point has been marked, and print the log + # message for the marked point for reference purposes + # + # Note this section also catches any other reference type (although there + # aren't any) and deals with them in the same way. + + echo "" + if [ "$newrev_type" = "commit" ]; then + echo $LOGBEGIN + git show --no-color --root -s $newrev + echo $LOGEND + else + # What can we do here? The tag marks an object that is not a commit, + # so there is no log for us to display. It's probably not wise to + # output git-cat-file as it could be a binary blob. We'll just say how + # big it is + echo "$newrev is a $newrev_type, and is $(git cat-file -s $newrev) bytes long." + fi +} + +# +# Called for the deletion of any other type of reference +# +generate_delete_general_email() +{ + echo " was $oldrev" + echo "" + echo $LOGEND + git show -s --pretty=oneline $oldrev + echo $LOGEND +} + +# ---------------------------- main() + +# --- Constants +EMAILPREFIX="[SCM] " +LOGBEGIN="- Log -----------------------------------------------------------------" +LOGEND="-----------------------------------------------------------------------" + +# --- Config +# Set GIT_DIR either from the working directory, or from the environment +# variable. +GIT_DIR=$(git rev-parse --git-dir 2>/dev/null) +if [ -z "$GIT_DIR" ]; then + echo >&2 "fatal: post-receive: GIT_DIR not set" + exit 1 +fi + +projectdesc=$(sed -e '1p' "$GIT_DIR/description") +# Check if the description is unchanged from it's default, and shorten it to a +# more manageable length if it is +if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null +then + projectdesc="UNNAMED PROJECT" +fi + +recipients=$(git repo-config hooks.mailinglist) +announcerecipients=$(git repo-config hooks.announcelist) +envelopesender=$(git-repo-config hooks.envelopesender) + +# --- Main loop +# Allow dual mode: run from the command line just like the update hook, or if +# no arguments are given then run as a hook script +if [ -n "$1" -a -n "$2" -a -n "$3" ]; then + # Output to the terminal in command line mode - if someone wanted to + # resend an email; they could redirect the output to sendmail themselves + PAGER= generate_email $2 $3 $1 +else + if [ -n "$envelopesender" ]; then + envelopesender="-f '$envelopesender'" + fi + + while read oldrev newrev refname + do + generate_email $oldrev $newrev $refname | + /usr/sbin/sendmail -t $envelopesender + done +fi diff --git a/templates/hooks--post-receive b/templates/hooks--post-receive new file mode 100644 index 0000000000..190de2688c --- /dev/null +++ b/templates/hooks--post-receive @@ -0,0 +1,17 @@ +#!/bin/sh +# +# An example hook script for the post-receive event +# +# This script is run after receive-pack has accepted a pack and the +# repository has been updated. It is passed arguments in through stdin +# in the form +# +# For example: +# aa453216d1b3e49e7f6f98441fa56946ddcd6a20 68f7abf4e6f922807889f52bc043ecd31b79f814 refs/heads/master +# +# see contrib/hooks/ for an sample, or uncomment the next line (on debian) +# + + +#. /usr/share/doc/git-core/contrib/hooks/post-receive-email + From 4f01748d51b530c297eeb5a0ece9af923d5db937 Mon Sep 17 00:00:00 2001 From: Julian Phillips Date: Tue, 27 Mar 2007 00:15:32 +0100 Subject: [PATCH 121/130] contrib/workdir: add a simple script to create a working directory Add a simple script to create a working directory that uses symlinks to point at an exisiting repository. This allows having different branches in different working directories but all from the same repository. Based on a description from Junio of how he creates multiple working directories[1]. With the following caveat: "This risks confusion for an uninitiated if you update a ref that is checked out in another working tree, but modulo that caveat it works reasonably well." [1] http://article.gmane.org/gmane.comp.version-control.git/41513/ Signed-off-by: Julian Phillips Signed-off-by: Junio C Hamano --- contrib/workdir/git-new-workdir | 57 +++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100755 contrib/workdir/git-new-workdir diff --git a/contrib/workdir/git-new-workdir b/contrib/workdir/git-new-workdir new file mode 100755 index 0000000000..9877b98508 --- /dev/null +++ b/contrib/workdir/git-new-workdir @@ -0,0 +1,57 @@ +#!/bin/sh + +usage () { + echo "usage:" $@ + exit 127 +} + +die () { + echo $@ + exit 128 +} + +if test $# -lt 2 || test $# -gt 3 +then + usage "$0 []" +fi + +orig_git=$1 +new_workdir=$2 +branch=$3 + +# want to make sure that what is pointed to has a .git directory ... +test -d "$orig_git/.git" || die "\"$orig_git\" is not a git repository!" + +# don't link to a workdir +if test -L "$orig_git/.git/config" +then + die "\"$orig_git\" is a working directory only, please specify" \ + "a complete repository." +fi + +# make sure the the links use full paths +orig_git=$(cd "$orig_git"; pwd) + +# create the workdir +mkdir -p "$new_workdir/.git" || die "unable to create \"$new_workdir\"!" + +# create the links to the original repo. explictly exclude index, HEAD and +# logs/HEAD from the list since they are purely related to the current working +# directory, and should not be shared. +for x in config refs logs/refs objects info hooks packed-refs remotes rr-cache +do + case $x in + */*) + mkdir -p "$(dirname "$new_workdir/.git/$x")" + ;; + esac + ln -s "$orig_git/.git/$x" "$new_workdir/.git/$x" +done + +# now setup the workdir +cd "$new_workdir" +# copy the HEAD from the original repository as a default branch +cp "$orig_git/.git/HEAD" .git/HEAD +# checkout the branch (either the same as HEAD from the original repository, or +# the one that was asked for) +git checkout -f $branch From a97e4075a16e0cbdf9c4aed736b5e762e035508b Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Sat, 31 Mar 2007 13:49:38 +0200 Subject: [PATCH 122/130] Keep rename/rename conflicts of intermediate merges while doing recursive merge This patch leaves the base name in the resulting intermediate tree, to propagate the conflict from intermediate merges up to the top-level merge. Signed-off-by: Alex Riesen Acked-by: Linus Torvalds Signed-off-by: Junio C Hamano --- merge-recursive.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/merge-recursive.c b/merge-recursive.c index c96e1a734c..e1aebd7727 100644 --- a/merge-recursive.c +++ b/merge-recursive.c @@ -278,8 +278,16 @@ static struct tree *git_write_tree(void) { struct tree *result = NULL; - if (unmerged_index()) + if (unmerged_index()) { + int i; + output(0, "There are unmerged index entries:"); + for (i = 0; i < active_nr; i++) { + struct cache_entry *ce = active_cache[i]; + if (ce_stage(ce)) + output(0, "%d %.*s", ce_stage(ce), ce_namelen(ce), ce->name); + } return NULL; + } if (!active_cache_tree) active_cache_tree = cache_tree(); @@ -735,8 +743,19 @@ static void conflict_rename_rename(struct rename *ren1, ren2_dst, branch1, dst_name2); remove_file(0, ren2_dst, 0); } - update_stages(dst_name1, NULL, ren1->pair->two, NULL, 1); - update_stages(dst_name2, NULL, NULL, ren2->pair->two, 1); + if (index_only) { + remove_file_from_cache(dst_name1); + remove_file_from_cache(dst_name2); + /* + * Uncomment to leave the conflicting names in the resulting tree + * + * update_file(0, ren1->pair->two->sha1, ren1->pair->two->mode, dst_name1); + * update_file(0, ren2->pair->two->sha1, ren2->pair->two->mode, dst_name2); + */ + } else { + update_stages(dst_name1, NULL, ren1->pair->two, NULL, 1); + update_stages(dst_name2, NULL, NULL, ren2->pair->two, 1); + } while (delp--) free(del[delp]); } @@ -852,10 +871,16 @@ static int process_renames(struct path_list *a_renames, if (strcmp(ren1_dst, ren2_dst) != 0) { clean_merge = 0; output(1, "CONFLICT (rename/rename): " - "Rename %s->%s in branch %s " - "rename %s->%s in %s", + "Rename \"%s\"->\"%s\" in branch \"%s\" " + "rename \"%s\"->\"%s\" in \"%s\"%s", src, ren1_dst, branch1, - src, ren2_dst, branch2); + src, ren2_dst, branch2, + index_only ? " (left unresolved)": ""); + if (index_only) { + remove_file_from_cache(src); + update_file(0, ren1->pair->one->sha1, + ren1->pair->one->mode, src); + } conflict_rename_rename(ren1, branch1, ren2, branch2); } else { struct merge_file_info mfi; From d6bad6610aece0bcaf4449ce170de22970793110 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 31 Mar 2007 14:00:18 -0700 Subject: [PATCH 123/130] git-svn: fail on rebase if we are unable to find a ref to rebase against If we're on an invalid HEAD, we should detect this and avoid attempting to continue. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- git-svn.perl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/git-svn.perl b/git-svn.perl index 278f45d6d0..d307d430f3 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -435,6 +435,9 @@ sub cmd_rebase { } my $gs = Git::SVN->find_by_url($url); + unless ($gs) { + die "Unable to determine remote information from URL: $url\n"; + } if (command(qw/diff-index HEAD --/)) { print STDERR "Cannot rebase with uncommited changes:\n"; command_noisy('status'); From d8b6a1a10b93666246984a50d64a163e71163aeb Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Sat, 31 Mar 2007 15:32:13 +0200 Subject: [PATCH 124/130] cvsserver: Don't lie about binary mode in asciidoc documentation The git-cvsserver documentation claims that the server will set -k modes if appropriate which is not really the case. On the other hand the available gitcvs.allbinary variable is not documented at all. Fix both these issues by rewording the related paragraph. Signed-off-by: Frank Lichtenheld Signed-off-by: Junio C Hamano --- Documentation/git-cvsserver.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Documentation/git-cvsserver.txt b/Documentation/git-cvsserver.txt index 1c6f6a7e27..85d0950cf4 100644 --- a/Documentation/git-cvsserver.txt +++ b/Documentation/git-cvsserver.txt @@ -134,9 +134,11 @@ checkout, diff, status, update, log, add, remove, commit. Legacy monitoring operations are not supported (edit, watch and related). Exports and tagging (tags and branches) are not supported at this stage. -The server will set the -k mode to binary when relevant. In proper GIT -tradition, the contents of the files are always respected. -No keyword expansion or newline munging is supported. +The server should set the -k mode to binary when relevant, however, +this is not really implemented yet. For now, you can force the server +to set `-kb` for all files by setting the `gitcvs.allbinary` config +variable. In proper GIT tradition, the contents of the files are +always respected. No keyword expansion or newline munging is supported. Dependencies ------------ From a8f4ef727a7e626f23878e7e3f9f19f0a1052df0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 2 Apr 2007 13:29:38 -0700 Subject: [PATCH 125/130] Hopefully final update to the draft Release Notes, preparing for 1.5.1 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.1.txt | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Documentation/RelNotes-1.5.1.txt b/Documentation/RelNotes-1.5.1.txt index f48d816c7b..a5d2dd32ff 100644 --- a/Documentation/RelNotes-1.5.1.txt +++ b/Documentation/RelNotes-1.5.1.txt @@ -90,7 +90,11 @@ Updates since v1.5.0 which does what the name suggests. -* Updated behaviour of existing commands. +* Updated behavior of existing commands. + + - "git-merge-recursive" used to barf when there are more than + one common ancestors for the merge, and merging them had a + rename/rename conflict. This has been fixed. - "git fsck" does not barf on corrupt loose objects. @@ -113,10 +117,10 @@ Updates since v1.5.0 allow users to explicitly override this heuristic based on paths. - - The behaviour of 'git-apply', when run in a subdirectory, + - The behavior of 'git-apply', when run in a subdirectory, without --index nor --cached were inconsistent with that of the command with these options. This was fixed to match the - behaviour with --index. A patch that is meant to be applied + behavior with --index. A patch that is meant to be applied with -p1 from the toplevel of the project tree can be applied with any custom -p option. A patch that is not relative to the toplevel needs to be applied with -p @@ -158,15 +162,17 @@ Updates since v1.5.0 the heaviest parts in C. - "git mailinfo" which splits an e-mail into a patch and the - metainformation was rewritten, thanks to Don Zickus. It - handles nested multipart better. + meta-information was rewritten, thanks to Don Zickus. It + handles nested multipart better. The command was broken for + a brief period on 'master' branch since 1.5.0 but the + breakage is fixed now. - send-email learned configurable bcc and chain-reply-to. - "git remote show $remote" also talks about branches that would be pushed if you run "git push remote". - - Using objects from packs is now seriouly optimized by clever + - Using objects from packs is now seriously optimized by clever use of a cache. This should be most noticeable in git-log family of commands that involve reading many tree objects. In addition, traversing revisions while filtering changes @@ -178,7 +184,8 @@ Updates since v1.5.0 - The part to send out notification e-mails was removed from the sample update hook, as it was not an appropriate place - to do so. + to do so. The proper place to do this is the new post-receive + hook. An example hook has been added to contrib/hooks/. * Others @@ -188,7 +195,7 @@ Updates since v1.5.0 -- exec >/var/tmp/1 -O=v1.5.1-rc3-18-ge881192 +O=v1.5.1-rc3-29-gd8b6a1a echo O=`git describe master` git shortlog --no-merges $O..master ^maint From eb3359663d62f35999330797455dbe738bd5ed99 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Apr 2007 16:28:46 -0700 Subject: [PATCH 126/130] rerere should not repeat the earlier hunks in later ones When a file has more then one conflicting hunks, it repeated the contents of previous hunks in output for later ones. Signed-off-by: Junio C Hamano --- builtin-rerere.c | 9 +++++++++ t/t4200-rerere.sh | 21 +++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/builtin-rerere.c b/builtin-rerere.c index 58c5fed91d..004eda2acd 100644 --- a/builtin-rerere.c +++ b/builtin-rerere.c @@ -78,6 +78,13 @@ static void append_line(struct buffer *buffer, const char *line) buffer->nr += len; } +static void clear_buffer(struct buffer *buffer) +{ + free(buffer->ptr); + buffer->ptr = NULL; + buffer->nr = buffer->alloc = 0; +} + static int handle_file(const char *path, unsigned char *sha1, const char *output) { @@ -131,6 +138,8 @@ static int handle_file(const char *path, SHA1_Update(&ctx, two->ptr, two->nr); SHA1_Update(&ctx, "\0", 1); } + clear_buffer(one); + clear_buffer(two); } else if (hunk == 1) append_line(one, buf); else if (hunk == 2) diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index c571a1bd74..69b8d26cd1 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -34,7 +34,8 @@ EOF git commit -q -a -m first git checkout -b second master -git show first:a1 | sed 's/To die, t/To die! T/' > a1 +git show first:a1 | +sed -e 's/To die, t/To die! T/' -e 's/life;$/life./' > a1 git commit -q -a -m second # activate rerere @@ -42,19 +43,26 @@ mkdir .git/rr-cache test_expect_failure 'conflicting merge' 'git pull . first' -sha1=4f58849a60b4f969a2848966b6d02893b783e8fb +sha1=$(sed -e 's/\t.*//' .git/rr-cache/MERGE_RR) rr=.git/rr-cache/$sha1 test_expect_success 'recorded preimage' "grep ======= $rr/preimage" test_expect_success 'no postimage or thisimage yet' \ "test ! -f $rr/postimage -a ! -f $rr/thisimage" +test_expect_success 'preimage have right number of lines' ' + + cnt=$(sed -ne "/^<<<<<<>>>>>>/p" $rr/preimage | wc -l) && + test "$cnt" = 10 + +' + git show first:a1 > a1 cat > expect << EOF --- a/a1 +++ b/a1 -@@ -6,11 +6,7 @@ +@@ -6,17 +6,9 @@ The heart-ache and the thousand natural shocks That flesh is heir to, 'tis a consummation Devoutly to be wish'd. @@ -66,8 +74,13 @@ cat > expect << EOF To sleep: perchance to dream: ay, there's the rub; For in that sleep of death what dreams may come When we have shuffled off this mortal coil, + Must give us pause: there's the respect +-<<<<<<< +-That makes calamity of so long life. +-======= + That makes calamity of so long life; +->>>>>>> EOF - git rerere diff > out test_expect_success 'rerere diff' 'diff -u expect out' From bbf4b41baff11d9fdc353c60527f258e84223121 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Tue, 3 Apr 2007 12:33:46 -0400 Subject: [PATCH 127/130] Plug memory leak in index-pack collision checking codepath. --- index-pack.c | 1 + 1 file changed, 1 insertion(+) diff --git a/index-pack.c b/index-pack.c index 6284fe3760..3c768fbc63 100644 --- a/index-pack.c +++ b/index-pack.c @@ -358,6 +358,7 @@ static void sha1_object(const void *data, unsigned long size, if (size != has_size || type != has_type || memcmp(data, has_data, size) != 0) die("SHA1 COLLISION FOUND WITH %s !", sha1_to_hex(sha1)); + free(has_data); } } From 04483524ecfe67e4d4f120b0bf6d91b43a02d40a Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Tue, 3 Apr 2007 18:27:28 +0200 Subject: [PATCH 128/130] Documentation: A few minor fixes to Git User's Manual Mainly consistent usage of "git command" and not "git-command" syntax Signed-off-by: Jakub Narebski Acked-by: J. Bruce Fields Signed-off-by: Junio C Hamano --- Documentation/user-manual.txt | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 1c49e6995b..574e9c0e50 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -84,7 +84,7 @@ $ git branch -r # list origin/master origin/next ... -$ git branch checkout -b masterwork origin/master +$ git checkout -b masterwork origin/master ----------------------------------------------- Fetch a branch from a different repository, and give it a new @@ -155,8 +155,8 @@ Make sure git knows who to blame: ------------------------------------------------ $ cat >~/.gitconfig <<\EOF [user] -name = Your Name Comes Here -email = you@yourdomain.example.com + name = Your Name Comes Here + email = you@yourdomain.example.com EOF ------------------------------------------------ @@ -195,7 +195,7 @@ Importing or exporting patches: ----------------------------------------------- $ git format-patch origin..HEAD # format a patch for each commit # in HEAD but not in origin -$ git-am mbox # import patches from the mailbox "mbox" +$ git am mbox # import patches from the mailbox "mbox" ----------------------------------------------- Fetch a branch in a different git repository, then merge into the @@ -579,7 +579,7 @@ cloned from, using gitlink:git-remote[1]: ------------------------------------------------- $ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git -$ git fetch +$ git fetch linux-nfs * refs/remotes/linux-nfs/master: storing branch 'master' ... commit: bf81b46 ------------------------------------------------- @@ -680,7 +680,7 @@ occasionally you may land on a commit that broke something unrelated; run ------------------------------------------------- -$ git bisect-visualize +$ git bisect visualize ------------------------------------------------- which will run gitk and label the commit it chose with a marker that @@ -765,7 +765,7 @@ We can also create a tag to refer to a particular commit; after running ------------------------------------------------- -$ git-tag stable-1 1b2e1d63ff +$ git tag stable-1 1b2e1d63ff ------------------------------------------------- You can use stable-1 to refer to the commit 1b2e1d63ff. @@ -909,7 +909,7 @@ name based on any tag it finds pointing to one of the commit's descendants: ------------------------------------------------- -$ git name-rev e05db0fd +$ git name-rev --tags e05db0fd e05db0fd tags/v1.5.0-rc1^0~23 ------------------------------------------------- @@ -918,7 +918,7 @@ revision using a tag on which the given commit is based: ------------------------------------------------- $ git describe e05db0fd -v1.5.0-rc0-ge05db0f +v1.5.0-rc0-260-ge05db0f ------------------------------------------------- but that may sometimes help you guess which tags might come after the @@ -1861,7 +1861,7 @@ Allow web browsing of a repository The gitweb cgi script provides users an easy way to browse your project's files and history without having to install git; see the file -gitweb/README in the git source tree for instructions on setting it up. +gitweb/INSTALL in the git source tree for instructions on setting it up. Examples -------- From 9694ec4533b30c1299e9ce7742c65c78b4fa3c5d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Apr 2007 11:31:21 -0700 Subject: [PATCH 129/130] GIT 1.5.0.7 Not that this release really matters, as we will be doing 1.5.1 tomorrow. This commit is to tie the loose ends and merge all of "maint" branch into "master" in preparation. Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.0.7.txt | 18 ++++++++++++++++++ GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 Documentation/RelNotes-1.5.0.7.txt diff --git a/Documentation/RelNotes-1.5.0.7.txt b/Documentation/RelNotes-1.5.0.7.txt new file mode 100644 index 0000000000..670ad32b85 --- /dev/null +++ b/Documentation/RelNotes-1.5.0.7.txt @@ -0,0 +1,18 @@ +GIT v1.5.0.7 Release Notes +========================== + +Fixes since v1.5.0.6 +-------------------- + +* Bugfixes + + - git-upload-pack failed to close unused pipe ends, resulting + in many zombies to hang around. + + - git-rerere was recording the contents of earlier hunks + duplicated in later hunks. This prevented resolving the same + conflict when performing the same merge the other way around. + +* Documentation + + - a few documentation fixes from Debian package maintainer. diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 6abd4cfc98..7213309483 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.0.6.GIT +DEF_VER=v1.5.0.7.GIT LF=' ' diff --git a/RelNotes b/RelNotes index 4e145f3021..1126dfef4f 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes-1.5.0.6.txt \ No newline at end of file +Documentation/RelNotes-1.5.0.7.txt \ No newline at end of file From 89815cab95268e8f0f58142b848ac4cd5e9cbdcb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 3 Apr 2007 22:47:01 -0700 Subject: [PATCH 130/130] GIT 1.5.1 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.1.txt | 183 +++++++++++++++++++++++++++++-- Documentation/git.txt | 18 +-- GIT-VERSION-GEN | 2 +- 3 files changed, 187 insertions(+), 16 deletions(-) diff --git a/Documentation/RelNotes-1.5.1.txt b/Documentation/RelNotes-1.5.1.txt index a5d2dd32ff..daed367270 100644 --- a/Documentation/RelNotes-1.5.1.txt +++ b/Documentation/RelNotes-1.5.1.txt @@ -192,13 +192,180 @@ Updates since v1.5.0 - git-revert, git-gc and git-cherry-pick are now built-ins. +Fixes since v1.5.0 +------------------ --- -exec >/var/tmp/1 -O=v1.5.1-rc3-29-gd8b6a1a -echo O=`git describe master` -git shortlog --no-merges $O..master ^maint +These are all in v1.5.0.x series. -# Local Variables: -# mode: text -# End: +* Documentation updates + + - Clarifications and corrections to 1.5.0 release notes. + + - The main documentation did not link to git-remote documentation. + + - Clarified introductory text of git-rebase documentation. + + - Converted remaining mentions of update-index on Porcelain + documents to git-add/git-rm. + + - Some i18n.* configuration variables were incorrectly + described as core.*; fixed. + + - added and clarified core.bare, core.legacyheaders configurations. + + - updated "git-clone --depth" documentation. + + - user-manual updates. + + - Options to 'git remote add' were described insufficiently. + + - Configuration format.suffix was not documented. + + - Other formatting and spelling fixes. + + - user-manual has better cross references. + + - gitweb installation/deployment procedure is now documented. + + +* Bugfixes + + - git-upload-pack closes unused pipe ends; earlier this caused + many zombies to hang around. + + - git-rerere was recording the contents of earlier hunks + duplicated in later hunks. This prevented resolving the same + conflict when performing the same merge the other way around. + + - git-add and git-update-index on a filesystem on which + executable bits are unreliable incorrectly reused st_mode + bits even when the path changed between symlink and regular + file. + + - git-daemon marks the listening sockets with FD_CLOEXEC so + that it won't be leaked into the children. + + - segfault from git-blame when the mandatory pathname + parameter was missing was fixed; usage() message is given + instead. + + - git-rev-list did not read $GIT_DIR/config file, which means + that did not honor i18n.logoutputencoding correctly. + + - Automated merge conflict handling when changes to symbolic + links conflicted were completely broken. The merge-resolve + strategy created a regular file with conflict markers in it + in place of the symbolic link. The default strategy, + merge-recursive was even more broken. It removed the path + that was pointed at by the symbolic link. Both of these + problems have been fixed. + + - 'git diff maint master next' did not correctly give combined + diff across three trees. + + - 'git fast-import' portability fix for Solaris. + + - 'git show-ref --verify' without arguments did not error out + but segfaulted. + + - 'git diff :tracked-file `pwd`/an-untracked-file' gave an extra + slashes after a/ and b/. + + - 'git format-patch' produced too long filenames if the commit + message had too long line at the beginning. + + - Running 'make all' and then without changing anything + running 'make install' still rebuilt some files. This + was inconvenient when building as yourself and then + installing as root (especially problematic when the source + directory is on NFS and root is mapped to nobody). + + - 'git-rerere' failed to deal with two unconflicted paths that + sorted next to each other. + + - 'git-rerere' attempted to open(2) a symlink and failed if + there was a conflict. Since a conflicting change to a + symlink would not benefit from rerere anyway, the command + now ignores conflicting changes to symlinks. + + - 'git-repack' did not like to pass more than 64 arguments + internally to underlying 'rev-list' logic, which made it + impossible to repack after accumulating many (small) packs + in the repository. + + - 'git-diff' to review the combined diff during a conflicted + merge were not reading the working tree version correctly + when changes to a symbolic link conflicted. It should have + read the data using readlink(2) but read from the regular + file the symbolic link pointed at. + + - 'git-remote' did not like period in a remote's name. + + - 'git.el' honors the commit coding system from the configuration. + + - 'blameview' in contrib/ correctly digs deeper when a line is + clicked. + + - 'http-push' correctly makes sure the remote side has leading + path. Earlier it started in the middle of the path, and + incorrectly. + + - 'git-merge' did not exit with non-zero status when the + working tree was dirty and cannot fast forward. It does + now. + + - 'cvsexportcommit' does not lose yet-to-be-used message file. + + - int-vs-size_t typefix when running combined diff on files + over 2GB long. + + - 'git apply --whitespace=strip' should not touch unmodified + lines. + + - 'git-mailinfo' choke when a logical header line was too long. + + - 'git show A..B' did not error out. Negative ref ("not A" in + this example) does not make sense for the purpose of the + command, so now it errors out. + + - 'git fmt-merge-msg --file' without file parameter did not + correctly error out. + + - 'git archimport' barfed upon encountering a commit without + summary. + + - 'git index-pack' did not protect itself from getting a short + read out of pread(2). + + - 'git http-push' had a few buffer overruns. + + - Build dependency fixes to rebuild fetch.o when other headers + change. + + - git.el does not add duplicate sign-off lines. + + - git-commit shows the full stat of the resulting commit, not + just about the files in the current directory, when run from + a subdirectory. + + - "git-checkout -m '@{8 hours ago}'" had a funny failure from + eval; fixed. + + - git-merge (hence git-pull) did not refuse fast-forwarding + when the working tree had local changes that would have + conflicted with it. + + - a handful small fixes to gitweb. + + - build procedure for user-manual is fixed not to require locally + installed stylesheets. + + - "git commit $paths" on paths whose earlier contents were + already updated in the index were failing out. + + +* Tweaks + + - sliding mmap() inefficiently mmaped the same region of a + packfile with an access pattern that used objects in the + reverse order. This has been made more efficient. diff --git a/Documentation/git.txt b/Documentation/git.txt index dceacfac11..9defc33273 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -35,19 +35,23 @@ ifdef::stalenotes[] You are reading the documentation for the latest version of git. Documentation for older releases are available here: -* link:v1.5.0.6/git.html[documentation for release 1.5.0.6] +* link:RelNotes-1.5.1.txt[release notes for 1.5.1] -* link:v1.5.0.6/RelNotes-1.5.0.6.txt[release notes for 1.5.0.6] +* link:v1.5.0.7/git.html[documentation for release 1.5.0.7] -* link:v1.5.0.5/RelNotes-1.5.0.5.txt[release notes for 1.5.0.5] +* link:RelNotes-1.5.0.7.txt[release notes for 1.5.0.7] -* link:v1.5.0.3/RelNotes-1.5.0.3.txt[release notes for 1.5.0.3] +* link:RelNotes-1.5.0.6.txt[release notes for 1.5.0.6] -* link:v1.5.0.2/RelNotes-1.5.0.2.txt[release notes for 1.5.0.2] +* link:RelNotes-1.5.0.5.txt[release notes for 1.5.0.5] -* link:v1.5.0.1/RelNotes-1.5.0.1.txt[release notes for 1.5.0.1] +* link:RelNotes-1.5.0.3.txt[release notes for 1.5.0.3] -* link:v1.5.0/RelNotes-1.5.0.txt[release notes for 1.5.0] +* link:RelNotes-1.5.0.2.txt[release notes for 1.5.0.2] + +* link:RelNotes-1.5.0.1.txt[release notes for 1.5.0.1] + +* link:RelNotes-1.5.0.txt[release notes for 1.5.0] * link:v1.4.4.4/git.html[documentation for release 1.4.4.4] diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 601f30f311..48715012be 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.1-rc3.GIT +DEF_VER=v1.5.1.GIT LF=' '