Merge with git://repo.or.cz/git.git#next.

This commit is contained in:
Johannes Sixt
2007-02-02 16:36:44 +01:00
28 changed files with 3623 additions and 121 deletions

View File

@@ -17,7 +17,7 @@ ARTICLES += hooks
ARTICLES += everyday
ARTICLES += git-tools
# with their own formatting rules.
SP_ARTICLES = glossary howto/revert-branch-rebase
SP_ARTICLES = glossary howto/revert-branch-rebase user-manual
DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES))
@@ -99,6 +99,12 @@ clean:
%.xml : %.txt
asciidoc -b docbook -d manpage -f asciidoc.conf $<
user-manual.xml: user-manual.txt user-manual.conf
asciidoc -b docbook -d book $<
user-manual.html: user-manual.xml
xmlto html-nochunks $<
glossary.html : glossary.txt sort_glossary.pl
cat $< | \
perl sort_glossary.pl | \

View File

@@ -0,0 +1,286 @@
/*
CSS stylesheet for XHTML produced by DocBook XSL stylesheets.
Tested with XSL stylesheets 1.61.2, 1.67.2
*/
span.strong {
font-weight: bold;
}
body blockquote {
margin-top: .75em;
line-height: 1.5;
margin-bottom: .75em;
}
html body {
margin: 1em 5% 1em 5%;
line-height: 1.2;
}
body div {
margin: 0;
}
h1, h2, h3, h4, h5, h6,
div.toc p b,
div.list-of-figures p b,
div.list-of-tables p b,
div.abstract p.title
{
color: #527bbd;
font-family: tahoma, verdana, sans-serif;
}
div.toc p:first-child,
div.list-of-figures p:first-child,
div.list-of-tables p:first-child,
div.example p.title
{
margin-bottom: 0.2em;
}
body h1 {
margin: .0em 0 0 -4%;
line-height: 1.3;
border-bottom: 2px solid silver;
}
body h2 {
margin: 0.5em 0 0 -4%;
line-height: 1.3;
border-bottom: 2px solid silver;
}
body h3 {
margin: .8em 0 0 -3%;
line-height: 1.3;
}
body h4 {
margin: .8em 0 0 -3%;
line-height: 1.3;
}
body h5 {
margin: .8em 0 0 -2%;
line-height: 1.3;
}
body h6 {
margin: .8em 0 0 -1%;
line-height: 1.3;
}
body hr {
border: none; /* Broken on IE6 */
}
div.footnotes hr {
border: 1px solid silver;
}
div.navheader th, div.navheader td, div.navfooter td {
font-family: sans-serif;
font-size: 0.9em;
font-weight: bold;
color: #527bbd;
}
div.navheader img, div.navfooter img {
border-style: none;
}
div.navheader a, div.navfooter a {
font-weight: normal;
}
div.navfooter hr {
border: 1px solid silver;
}
body td {
line-height: 1.2
}
body th {
line-height: 1.2;
}
ol {
line-height: 1.2;
}
ul, body dir, body menu {
line-height: 1.2;
}
html {
margin: 0;
padding: 0;
}
body h1, body h2, body h3, body h4, body h5, body h6 {
margin-left: 0
}
body pre {
margin: 0.5em 10% 0.5em 1em;
line-height: 1.0;
color: navy;
}
tt.literal, code.literal {
color: navy;
}
div.literallayout p {
padding: 0em;
margin: 0em;
}
div.literallayout {
font-family: monospace;
# margin: 0.5em 10% 0.5em 1em;
margin: 0em;
color: navy;
border: 1px solid silver;
background: #f4f4f4;
padding: 0.5em;
}
.programlisting, .screen {
border: 1px solid silver;
background: #f4f4f4;
margin: 0.5em 10% 0.5em 0;
padding: 0.5em 1em;
}
div.sidebar {
background: #ffffee;
margin: 1.0em 10% 0.5em 0;
padding: 0.5em 1em;
border: 1px solid silver;
}
div.sidebar * { padding: 0; }
div.sidebar div { margin: 0; }
div.sidebar p.title {
font-family: sans-serif;
margin-top: 0.5em;
margin-bottom: 0.2em;
}
div.bibliomixed {
margin: 0.5em 5% 0.5em 1em;
}
div.glossary dt {
font-weight: bold;
}
div.glossary dd p {
margin-top: 0.2em;
}
dl {
margin: .8em 0;
line-height: 1.2;
}
dt {
margin-top: 0.5em;
}
dt span.term {
font-style: italic;
}
div.variablelist dd p {
margin-top: 0;
}
div.itemizedlist li, div.orderedlist li {
margin-left: -0.8em;
margin-top: 0.5em;
}
ul, ol {
list-style-position: outside;
}
div.sidebar ul, div.sidebar ol {
margin-left: 2.8em;
}
div.itemizedlist p.title,
div.orderedlist p.title,
div.variablelist p.title
{
margin-bottom: -0.8em;
}
div.revhistory table {
border-collapse: collapse;
border: none;
}
div.revhistory th {
border: none;
color: #527bbd;
font-family: tahoma, verdana, sans-serif;
}
div.revhistory td {
border: 1px solid silver;
}
/* Keep TOC and index lines close together. */
div.toc dl, div.toc dt,
div.list-of-figures dl, div.list-of-figures dt,
div.list-of-tables dl, div.list-of-tables dt,
div.indexdiv dl, div.indexdiv dt
{
line-height: normal;
margin-top: 0;
margin-bottom: 0;
}
/*
Table styling does not work because of overriding attributes in
generated HTML.
*/
div.table table,
div.informaltable table
{
margin-left: 0;
margin-right: 5%;
margin-bottom: 0.8em;
}
div.informaltable table
{
margin-top: 0.4em
}
div.table thead,
div.table tfoot,
div.table tbody,
div.informaltable thead,
div.informaltable tfoot,
div.informaltable tbody
{
/* No effect in IE6. */
border-top: 2px solid #527bbd;
border-bottom: 2px solid #527bbd;
}
div.table thead, div.table tfoot,
div.informaltable thead, div.informaltable tfoot
{
font-weight: bold;
}
div.mediaobject img {
border: 1px solid silver;
margin-bottom: 0.8em;
}
div.figure p.title,
div.table p.title
{
margin-top: 1em;
margin-bottom: 0.4em;
}
@media print {
div.navheader, div.navfooter { display: none; }
}

View File

@@ -19,7 +19,9 @@ or '-s' is used to find the object size.
OPTIONS
-------
<object>::
The sha1 identifier of the object.
The name of the object to show.
For a more complete list of ways to spell object names, see
"SPECIFYING REVISIONS" section in gitlink:git-rev-parse[1].
-t::
Instead of the content, show the object type identified by

View File

@@ -9,7 +9,7 @@ SYNOPSIS
--------
[verse]
'git-checkout' [-f] [-b <new_branch> [-l]] [-m] [<branch>]
'git-checkout' [<branch>] <paths>...
'git-checkout' [<tree-ish>] <paths>...
DESCRIPTION
-----------
@@ -22,11 +22,13 @@ be created.
When <paths> are given, this command does *not* switch
branches. It updates the named paths in the working tree from
the index file (i.e. it runs `git-checkout-index -f -u`). In
the index file (i.e. it runs `git-checkout-index -f -u`), or a
named commit. In
this case, `-f` and `-b` options are meaningless and giving
either of them results in an error. <branch> argument can be
used to specify a specific tree-ish to update the index for the
given paths before updating the working tree.
either of them results in an error. <tree-ish> argument can be
used to specify a specific tree-ish (i.e. commit, tag or tree)
to update the index for the given paths before updating the
working tree.
OPTIONS

View File

@@ -22,6 +22,9 @@ See this link:tutorial.html[tutorial] to get started, then see
link:everyday.html[Everyday Git] for a useful minimum set of commands, and
"man git-commandname" for documentation of each command. CVS users may
also want to read link:cvs-migration.html[CVS migration].
link:user-manual.html[Git User's Manual] is still work in
progress, but when finished hopefully it will guide a new user
in a coherent way to git enlightenment ;-).
The COMMAND is either a name of a Git command (see below) or an alias
as defined in the configuration file (see gitlink:git-config[1]).

View File

@@ -0,0 +1,21 @@
[titles]
underlines="__","==","--","~~","^^"
[attributes]
caret=^
startsb=&#91;
endsb=&#93;
tilde=&#126;
[gitlink-inlinemacro]
<ulink url="{target}.html">{target}{0?({0})}</ulink>
ifdef::backend-docbook[]
# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this.
[listingblock]
<example><title>{title}</title>
<literallayout>
|
</literallayout>
{title#}</example>
endif::backend-docbook[]

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
DEF_VER=v1.5.0-rc2.GIT
DEF_VER=v1.5.0-rc3.GIT
LF='
'

View File

@@ -284,6 +284,7 @@ BUILTIN_OBJS = \
builtin-diff-tree.o \
builtin-fmt-merge-msg.o \
builtin-for-each-ref.o \
builtin-fsck.o \
builtin-grep.o \
builtin-init-db.o \
builtin-log.o \

View File

@@ -77,6 +77,10 @@ struct origin {
char path[FLEX_ARRAY];
};
/*
* Given an origin, prepare mmfile_t structure to be used by the
* diff machinery
*/
static char *fill_origin_blob(struct origin *o, mmfile_t *file)
{
if (!o->file.ptr) {
@@ -91,6 +95,10 @@ static char *fill_origin_blob(struct origin *o, mmfile_t *file)
return file->ptr;
}
/*
* Origin is refcounted and usually we keep the blob contents to be
* reused.
*/
static inline struct origin *origin_incref(struct origin *o)
{
if (o)
@@ -108,6 +116,11 @@ static void origin_decref(struct origin *o)
}
}
/*
* Each group of lines is described by a blame_entry; it can be split
* as we pass blame to the parents. They form a linked list in the
* scoreboard structure, sorted by the target line number.
*/
struct blame_entry {
struct blame_entry *prev;
struct blame_entry *next;
@@ -134,19 +147,24 @@ struct blame_entry {
int s_lno;
/* how significant this entry is -- cached to avoid
* scanning the lines over and over
* scanning the lines over and over.
*/
unsigned score;
};
/*
* The current state of the blame assignment.
*/
struct scoreboard {
/* the final commit (i.e. where we started digging from) */
struct commit *final;
const char *path;
/* the contents in the final; pointed into by buf pointers of
* blame_entries
/*
* The contents in the final image.
* Used by many functions to obtain contents of the nth line,
* indexed with scoreboard.lineno[blame_entry.lno].
*/
const char *final_buf;
unsigned long final_buf_size;
@@ -171,6 +189,11 @@ static int cmp_suspect(struct origin *a, struct origin *b)
static void sanity_check_refcnt(struct scoreboard *);
/*
* If two blame entries that are next to each other came from
* contiguous lines in the same origin (i.e. <commit, path> pair),
* merge them together.
*/
static void coalesce(struct scoreboard *sb)
{
struct blame_entry *ent, *next;
@@ -194,6 +217,12 @@ static void coalesce(struct scoreboard *sb)
sanity_check_refcnt(sb);
}
/*
* Given a commit and a path in it, create a new origin structure.
* The callers that add blame to the scoreboard should use
* get_origin() to obtain shared, refcounted copy instead of calling
* this function directly.
*/
static struct origin *make_origin(struct commit *commit, const char *path)
{
struct origin *o;
@@ -204,6 +233,9 @@ static struct origin *make_origin(struct commit *commit, const char *path)
return o;
}
/*
* Locate an existing origin or create a new one.
*/
static struct origin *get_origin(struct scoreboard *sb,
struct commit *commit,
const char *path)
@@ -218,6 +250,13 @@ static struct origin *get_origin(struct scoreboard *sb,
return make_origin(commit, path);
}
/*
* Fill the blob_sha1 field of an origin if it hasn't, so that later
* call to fill_origin_blob() can use it to locate the data. blob_sha1
* for an origin is also used to pass the blame for the entire file to
* the parent to detect the case where a child's blob is identical to
* that of its parent's.
*/
static int fill_blob_sha1(struct origin *origin)
{
unsigned mode;
@@ -238,6 +277,10 @@ static int fill_blob_sha1(struct origin *origin)
return -1;
}
/*
* We have an origin -- check if the same path exists in the
* parent and return an origin structure to represent it.
*/
static struct origin *find_origin(struct scoreboard *sb,
struct commit *parent,
struct origin *origin)
@@ -247,12 +290,26 @@ static struct origin *find_origin(struct scoreboard *sb,
const char *paths[2];
if (parent->util) {
/* This is a freestanding copy of origin and not
* refcounted.
/*
* Each commit object can cache one origin in that
* commit. This is a freestanding copy of origin and
* not refcounted.
*/
struct origin *cached = parent->util;
if (!strcmp(cached->path, origin->path)) {
/*
* The same path between origin and its parent
* without renaming -- the most common case.
*/
porigin = get_origin(sb, parent, cached->path);
/*
* If the origin was newly created (i.e. get_origin
* would call make_origin if none is found in the
* scoreboard), it does not know the blob_sha1,
* so copy it. Otherwise porigin was in the
* scoreboard and already knows blob_sha1.
*/
if (porigin->refcnt == 1)
hashcpy(porigin->blob_sha1, cached->blob_sha1);
return porigin;
@@ -309,7 +366,13 @@ static struct origin *find_origin(struct scoreboard *sb,
}
diff_flush(&diff_opts);
if (porigin) {
/*
* Create a freestanding copy that is not part of
* the refcounted origin found in the scoreboard, and
* cache it in the commit.
*/
struct origin *cached;
cached = make_origin(porigin->commit, porigin->path);
hashcpy(cached->blob_sha1, porigin->blob_sha1);
parent->util = cached;
@@ -317,6 +380,10 @@ static struct origin *find_origin(struct scoreboard *sb,
return porigin;
}
/*
* We have an origin -- find the path that corresponds to it in its
* parent and return an origin structure to represent it.
*/
static struct origin *find_rename(struct scoreboard *sb,
struct commit *parent,
struct origin *origin)
@@ -353,6 +420,9 @@ static struct origin *find_rename(struct scoreboard *sb,
return porigin;
}
/*
* Parsing of patch chunks...
*/
struct chunk {
/* line number in postimage; up to but not including this
* line is the same as preimage
@@ -454,6 +524,11 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
return state.ret;
}
/*
* Run diff between two origins and grab the patch output, so that
* we can pass blame for lines origin is currently suspected for
* to its parent.
*/
static struct patch *get_patch(struct origin *parent, struct origin *origin)
{
mmfile_t file_p, file_o;
@@ -474,6 +549,10 @@ static void free_patch(struct patch *p)
free(p);
}
/*
* Link in a new blame entry to the scorebord. Entries that cover the
* same line range have been removed from the scoreboard previously.
*/
static void add_blame_entry(struct scoreboard *sb, struct blame_entry *e)
{
struct blame_entry *ent, *prev = NULL;
@@ -497,6 +576,12 @@ static void add_blame_entry(struct scoreboard *sb, struct blame_entry *e)
e->next->prev = e;
}
/*
* src typically is on-stack; we want to copy the information in it to
* an malloced blame_entry that is already on the linked list of the
* scoreboard. The origin of dst loses a refcnt while the origin of src
* gains one.
*/
static void dup_entry(struct blame_entry *dst, struct blame_entry *src)
{
struct blame_entry *p, *n;
@@ -516,25 +601,25 @@ static const char *nth_line(struct scoreboard *sb, int lno)
return sb->final_buf + sb->lineno[lno];
}
/*
* It is known that lines between tlno to same came from parent, and e
* has an overlap with that range. it also is known that parent's
* line plno corresponds to e's line tlno.
*
* <---- e ----->
* <------>
* <------------>
* <------------>
* <------------------>
*
* Split e into potentially three parts; before this chunk, the chunk
* to be blamed for the parent, and after that portion.
*/
static void split_overlap(struct blame_entry *split,
struct blame_entry *e,
int tlno, int plno, int same,
struct origin *parent)
{
/* it is known that lines between tlno to same came from
* parent, and e has an overlap with that range. it also is
* known that parent's line plno corresponds to e's line tlno.
*
* <---- e ----->
* <------>
* <------------>
* <------------>
* <------------------>
*
* Potentially we need to split e into three parts; before
* this chunk, the chunk to be blamed for parent, and after
* that portion.
*/
int chunk_end_lno;
memset(split, 0, sizeof(struct blame_entry [3]));
@@ -564,11 +649,20 @@ static void split_overlap(struct blame_entry *split,
chunk_end_lno = e->lno + e->num_lines;
split[1].num_lines = chunk_end_lno - split[1].lno;
/*
* if it turns out there is nothing to blame the parent for,
* forget about the splitting. !split[1].suspect signals this.
*/
if (split[1].num_lines < 1)
return;
split[1].suspect = origin_incref(parent);
}
/*
* split_overlap() divided an existing blame e into up to three parts
* in split. Adjust the linked list of blames in the scoreboard to
* reflect the split.
*/
static void split_blame(struct scoreboard *sb,
struct blame_entry *split,
struct blame_entry *e)
@@ -576,21 +670,27 @@ static void split_blame(struct scoreboard *sb,
struct blame_entry *new_entry;
if (split[0].suspect && split[2].suspect) {
/* we need to split e into two and add another for parent */
/* The first part (reuse storage for the existing entry e) */
dup_entry(e, &split[0]);
/* The last part -- me */
new_entry = xmalloc(sizeof(*new_entry));
memcpy(new_entry, &(split[2]), sizeof(struct blame_entry));
add_blame_entry(sb, new_entry);
/* ... and the middle part -- parent */
new_entry = xmalloc(sizeof(*new_entry));
memcpy(new_entry, &(split[1]), sizeof(struct blame_entry));
add_blame_entry(sb, new_entry);
}
else if (!split[0].suspect && !split[2].suspect)
/* parent covers the entire area */
/*
* The parent covers the entire area; reuse storage for
* e and replace it with the parent.
*/
dup_entry(e, &split[1]);
else if (split[0].suspect) {
/* me and then parent */
dup_entry(e, &split[0]);
new_entry = xmalloc(sizeof(*new_entry));
@@ -598,6 +698,7 @@ static void split_blame(struct scoreboard *sb,
add_blame_entry(sb, new_entry);
}
else {
/* parent and then me */
dup_entry(e, &split[1]);
new_entry = xmalloc(sizeof(*new_entry));
@@ -628,6 +729,10 @@ static void split_blame(struct scoreboard *sb,
}
}
/*
* After splitting the blame, the origins used by the
* on-stack blame_entry should lose one refcnt each.
*/
static void decref_split(struct blame_entry *split)
{
int i;
@@ -636,6 +741,10 @@ static void decref_split(struct blame_entry *split)
origin_decref(split[i].suspect);
}
/*
* Helper for blame_chunk(). blame_entry e is known to overlap with
* the patch hunk; split it and pass blame to the parent.
*/
static void blame_overlap(struct scoreboard *sb, struct blame_entry *e,
int tlno, int plno, int same,
struct origin *parent)
@@ -648,6 +757,9 @@ static void blame_overlap(struct scoreboard *sb, struct blame_entry *e,
decref_split(split);
}
/*
* Find the line number of the last line the target is suspected for.
*/
static int find_last_in_target(struct scoreboard *sb, struct origin *target)
{
struct blame_entry *e;
@@ -662,6 +774,11 @@ static int find_last_in_target(struct scoreboard *sb, struct origin *target)
return last_in_target;
}
/*
* Process one hunk from the patch between the current suspect for
* blame_entry e and its parent. Find and split the overlap, and
* pass blame to the overlapping part to the parent.
*/
static void blame_chunk(struct scoreboard *sb,
int tlno, int plno, int same,
struct origin *target, struct origin *parent)
@@ -678,6 +795,11 @@ static void blame_chunk(struct scoreboard *sb,
}
}
/*
* We are looking at the origin 'target' and aiming to pass blame
* for the lines it is suspected to its parent. Run diff to find
* which lines came from parent and pass blame for them.
*/
static int pass_blame_to_parent(struct scoreboard *sb,
struct origin *target,
struct origin *parent)
@@ -698,13 +820,22 @@ static int pass_blame_to_parent(struct scoreboard *sb,
plno = chunk->p_next;
tlno = chunk->t_next;
}
/* rest (i.e. anything above tlno) are the same as parent */
/* The rest (i.e. anything after tlno) are the same as the parent */
blame_chunk(sb, tlno, plno, last_in_target, target, parent);
free_patch(patch);
return 0;
}
/*
* The lines in blame_entry after splitting blames many times can become
* very small and trivial, and at some point it becomes pointless to
* blame the parents. E.g. "\t\t}\n\t}\n\n" appears everywhere in any
* ordinary C program, and it is not worth to say it was copied from
* totally unrelated file in the parent.
*
* Compute how trivial the lines in the blame_entry are.
*/
static unsigned ent_score(struct scoreboard *sb, struct blame_entry *e)
{
unsigned score;
@@ -726,6 +857,12 @@ static unsigned ent_score(struct scoreboard *sb, struct blame_entry *e)
return score;
}
/*
* best_so_far[] and this[] are both a split of an existing blame_entry
* that passes blame to the parent. Maintain best_so_far the best split
* so far, by comparing this and best_so_far and copying this into
* bst_so_far as needed.
*/
static void copy_split_if_better(struct scoreboard *sb,
struct blame_entry *best_so_far,
struct blame_entry *this)
@@ -745,6 +882,11 @@ static void copy_split_if_better(struct scoreboard *sb,
memcpy(best_so_far, this, sizeof(struct blame_entry [3]));
}
/*
* Find the lines from parent that are the same as ent so that
* we can pass blames to it. file_p has the blob contents for
* the parent.
*/
static void find_copy_in_blob(struct scoreboard *sb,
struct blame_entry *ent,
struct origin *parent,
@@ -757,6 +899,9 @@ static void find_copy_in_blob(struct scoreboard *sb,
struct patch *patch;
int i, plno, tlno;
/*
* Prepare mmfile that contains only the lines in ent.
*/
cp = nth_line(sb, ent->lno);
file_o.ptr = (char*) cp;
cnt = ent->num_lines;
@@ -792,6 +937,10 @@ static void find_copy_in_blob(struct scoreboard *sb,
free_patch(patch);
}
/*
* See if lines currently target is suspected for can be attributed to
* parent.
*/
static int find_move_in_parent(struct scoreboard *sb,
struct origin *target,
struct origin *parent)
@@ -826,12 +975,15 @@ static int find_move_in_parent(struct scoreboard *sb,
return 0;
}
struct blame_list {
struct blame_entry *ent;
struct blame_entry split[3];
};
/*
* Count the number of entries the target is suspected for,
* and prepare a list of entry and the best split.
*/
static struct blame_list *setup_blame_list(struct scoreboard *sb,
struct origin *target,
int *num_ents_p)
@@ -840,9 +992,6 @@ static struct blame_list *setup_blame_list(struct scoreboard *sb,
int num_ents, i;
struct blame_list *blame_list = NULL;
/* Count the number of entries the target is suspected for,
* and prepare a list of entry and the best split.
*/
for (e = sb->ent, num_ents = 0; e; e = e->next)
if (!e->guilty && !cmp_suspect(e->suspect, target))
num_ents++;
@@ -856,6 +1005,11 @@ static struct blame_list *setup_blame_list(struct scoreboard *sb,
return blame_list;
}
/*
* For lines target is suspected for, see if we can find code movement
* across file boundary from the parent commit. porigin is the path
* in the parent we already tried.
*/
static int find_copy_in_parent(struct scoreboard *sb,
struct origin *target,
struct commit *parent,
@@ -956,7 +1110,8 @@ static int find_copy_in_parent(struct scoreboard *sb,
return retval;
}
/* The blobs of origin and porigin exactly match, so everything
/*
* The blobs of origin and porigin exactly match, so everything
* origin is suspected for can be blamed on the parent.
*/
static void pass_whole_blame(struct scoreboard *sb,
@@ -1041,7 +1196,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
}
/*
* Optionally run "miff" to find moves in parents' files here.
* Optionally find moves in parents' files.
*/
if (opt & PICKAXE_BLAME_MOVE)
for (i = 0, parent = commit->parents;
@@ -1055,7 +1210,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
}
/*
* Optionally run "ciff" to find copies from parents' files here.
* Optionally find copies from parents' files.
*/
if (opt & PICKAXE_BLAME_COPY)
for (i = 0, parent = commit->parents;
@@ -1072,6 +1227,9 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
origin_decref(parent_origin[i]);
}
/*
* Information on commits, used for output.
*/
struct commit_info
{
char *author;
@@ -1088,6 +1246,9 @@ struct commit_info
char *summary;
};
/*
* Parse author/committer line in the commit object buffer
*/
static void get_ac_line(const char *inbuf, const char *what,
int bufsz, char *person, char **mail,
unsigned long *time, char **tz)
@@ -1142,7 +1303,8 @@ static void get_commit_info(struct commit *commit,
static char committer_buf[1024];
static char summary_buf[1024];
/* We've operated without save_commit_buffer, so
/*
* We've operated without save_commit_buffer, so
* we now need to populate them for output.
*/
if (!commit->buffer) {
@@ -1182,6 +1344,10 @@ static void get_commit_info(struct commit *commit,
summary_buf[len] = 0;
}
/*
* To allow LF and other nonportable characters in pathnames,
* they are c-style quoted as needed.
*/
static void write_filename_info(const char *path)
{
printf("filename ");
@@ -1189,6 +1355,10 @@ static void write_filename_info(const char *path)
putchar('\n');
}
/*
* The blame_entry is found to be guilty for the range. Mark it
* as such, and show it in incremental output.
*/
static void found_guilty_entry(struct blame_entry *ent)
{
if (ent->guilty)
@@ -1220,6 +1390,11 @@ static void found_guilty_entry(struct blame_entry *ent)
}
}
/*
* The main loop -- while the scoreboard has lines whose true origin
* is still unknown, pick one brame_entry, and allow its current
* suspect to pass blames to its parents.
*/
static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
{
while (1) {
@@ -1234,12 +1409,16 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
if (!suspect)
return; /* all done */
/*
* We will use this suspect later in the loop,
* so hold onto it in the meantime.
*/
origin_incref(suspect);
commit = suspect->commit;
if (!commit->object.parsed)
parse_commit(commit);
if (!(commit->object.flags & UNINTERESTING) &&
!(revs->max_age != -1 && commit->date < revs->max_age))
!(revs->max_age != -1 && commit->date < revs->max_age))
pass_blame(sb, suspect, opt);
else {
commit->object.flags |= UNINTERESTING;
@@ -1431,6 +1610,10 @@ static void output(struct scoreboard *sb, int option)
}
}
/*
* To allow quick access to the contents of nth line in the
* final image, prepare an index in the scoreboard.
*/
static int prepare_lines(struct scoreboard *sb)
{
const char *buf = sb->final_buf;
@@ -1458,6 +1641,11 @@ static int prepare_lines(struct scoreboard *sb)
return sb->num_lines;
}
/*
* Add phony grafts for use with -S; this is primarily to
* support git-cvsserver that wants to give a linear history
* to its clients.
*/
static int read_ancestry(const char *graft_file)
{
FILE *fp = fopen(graft_file, "r");
@@ -1475,6 +1663,9 @@ static int read_ancestry(const char *graft_file)
return 0;
}
/*
* How many columns do we need to show line numbers in decimal?
*/
static int lineno_width(int lines)
{
int i, width;
@@ -1484,6 +1675,10 @@ static int lineno_width(int lines)
return width;
}
/*
* How many columns do we need to show line numbers, authors,
* and filenames?
*/
static void find_alignment(struct scoreboard *sb, int *option)
{
int longest_src_lines = 0;
@@ -1522,6 +1717,10 @@ static void find_alignment(struct scoreboard *sb, int *option)
max_score_digits = lineno_width(largest_score);
}
/*
* For debugging -- origin is refcounted, and this asserts that
* we do not underflow.
*/
static void sanity_check_refcnt(struct scoreboard *sb)
{
int baa = 0;
@@ -1543,8 +1742,9 @@ static void sanity_check_refcnt(struct scoreboard *sb)
ent->suspect->refcnt = -ent->suspect->refcnt;
}
for (ent = sb->ent; ent; ent = ent->next) {
/* then pick each and see if they have the the correct
* refcnt.
/*
* ... then pick each and see if they have the the
* correct refcnt.
*/
int found;
struct blame_entry *e;
@@ -1574,6 +1774,10 @@ static void sanity_check_refcnt(struct scoreboard *sb)
}
}
/*
* Used for the command line parsing; check if the path exists
* in the working tree.
*/
static int has_path_in_work_tree(const char *path)
{
struct stat st;
@@ -1596,6 +1800,9 @@ static const char *add_prefix(const char *prefix, const char *path)
return prefix_path(prefix, strlen(prefix), path);
}
/*
* Parsing of (comma separated) one item in the -L option
*/
static const char *parse_loc(const char *spec,
struct scoreboard *sb, long lno,
long begin, long *ret)
@@ -1670,6 +1877,9 @@ static const char *parse_loc(const char *spec,
}
}
/*
* Parsing of -L option
*/
static void prepare_blame_range(struct scoreboard *sb,
const char *bottomtop,
long lno,
@@ -1788,7 +1998,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
if (!blame_copy_score)
blame_copy_score = BLAME_DEFAULT_COPY_SCORE;
/* We have collected options unknown to us in argv[1..unk]
/*
* We have collected options unknown to us in argv[1..unk]
* which are to be passed to revision machinery if we are
* going to do the "bottom" procesing.
*
@@ -1868,7 +2079,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
if (final_commit_name)
argv[unk++] = final_commit_name;
/* Now we got rev and path. We do not want the path pruning
/*
* Now we got rev and path. We do not want the path pruning
* but we may want "bottom" processing.
*/
argv[unk++] = "--"; /* terminate the rev name */
@@ -1878,7 +2090,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
setup_revisions(unk, argv, &revs, "HEAD");
memset(&sb, 0, sizeof(sb));
/* There must be one and only one positive commit in the
/*
* There must be one and only one positive commit in the
* revs->pending array.
*/
for (i = 0; i < revs.pending.nr; i++) {
@@ -1899,7 +2112,10 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
}
if (!sb.final) {
/* "--not A B -- path" without anything positive */
/*
* "--not A B -- path" without anything positive;
* default to HEAD.
*/
unsigned char head_sha1[20];
final_commit_name = "HEAD";
@@ -1909,7 +2125,8 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
add_pending_object(&revs, &(sb.final->object), "HEAD");
}
/* If we have bottom, this will mark the ancestors of the
/*
* If we have bottom, this will mark the ancestors of the
* bottom commits we would reach while traversing as
* uninteresting.
*/

View File

@@ -571,12 +571,11 @@ static int fsck_cache_tree(struct cache_tree *it)
return err;
}
int main(int argc, char **argv)
int cmd_fsck(int argc, char **argv, const char *prefix)
{
int i, heads;
track_object_refs = 1;
setup_git_directory();
for (i = 1; i < argc; i++) {
const char *arg = argv[i];

View File

@@ -501,6 +501,7 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
for (i = 1 ; i < argc; i++) {
const char *path = argv[i];
const char *p;
if (allow_options && *path == '-') {
if (!strcmp(path, "--")) {
@@ -616,9 +617,12 @@ int cmd_update_index(int argc, const char **argv, const char *prefix)
usage(update_index_usage);
die("unknown option %s", path);
}
update_one(path, prefix, prefix_length);
p = prefix_path(prefix, prefix_length, path);
update_one(p, NULL, 0);
if (set_executable_bit)
chmod_path(set_executable_bit, path);
chmod_path(set_executable_bit, p);
if (p < path || p > path + strlen(path))
free((char*)p);
}
if (read_from_stdin) {
struct strbuf buf;

View File

@@ -61,10 +61,8 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
lock = lock_any_ref_for_update(refname, oldval ? oldsha1 : NULL);
if (!lock)
return 1;
die("%s: cannot lock the ref", refname);
if (write_ref_sha1(lock, sha1, msg) < 0)
return 1;
/* write_ref_sha1 always unlocks the ref, no need to do it explicitly */
die("%s: cannot update the ref", refname);
return 0;
}

View File

@@ -34,6 +34,7 @@ extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
extern int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
extern int cmd_fsck(int argc, const char **argv, const char *prefix);
extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
extern int cmd_grep(int argc, const char **argv, const char *prefix);
extern int cmd_help(int argc, const char **argv, const char *prefix);

View File

@@ -28,7 +28,8 @@ $fileview->get_column(0)->set_spacing(0);
$fileview->set_size_request(1024, 768);
$fileview->set_rules_hint(1);
open(my $fh, '<', $fn)
my $fh;
open($fh, '-|', "git cat-file blob HEAD:$fn")
or die "unable to open $fn: $!";
while(<$fh>) {
chomp;

View File

@@ -155,9 +155,9 @@ then
detached="$new"
if test -n "$oldbranch"
then
detach_warn="warning: you are not on ANY branch anymore.
If you meant to create a new branch from this checkout, you may still do
so (now or later) by using -b with the checkout command again. Example:
detach_warn="Note: you are not on any branch and are at commit \"$new_name\"
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 <new_branch_name>"
fi
elif test -z "$oldbranch" && test -n "$branch"
@@ -235,7 +235,7 @@ else
saved_err=$?
if test "$saved_err" = 0
then
test "$new" = "$old" || git diff-index --name-status "$new"
git diff-index --name-status "$new"
fi
(exit $saved_err)
fi
@@ -258,6 +258,12 @@ 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 -n "$newbranch"
then
echo >&2 "Switched to a new branch \"$branch\""
else
echo >&2 "Switched to branch \"$branch\""
fi
elif test -n "$detached"
then
# NEEDSWORK: we would want a command to detach the HEAD

View File

@@ -66,48 +66,6 @@ Perhaps git-update-server-info needs to be run there?"
rm -f "$GIT_DIR/REMOTE_HEAD"
}
# Read git-fetch-pack -k output and store the remote branches.
copy_refs='
use File::Path qw(mkpath);
use File::Basename qw(dirname);
my $git_dir = $ARGV[0];
my $use_separate_remote = $ARGV[1];
my $origin = $ARGV[2];
my $branch_top = ($use_separate_remote ? "remotes/$origin" : "heads");
my $tag_top = "tags";
sub store {
my ($sha1, $name, $top) = @_;
$name = "$git_dir/refs/$top/$name";
mkpath(dirname($name));
open O, ">", "$name";
print O "$sha1\n";
close O;
}
open FH, "<", "$git_dir/CLONE_HEAD";
while (<FH>) {
my ($sha1, $name) = /^([0-9a-f]{40})\s(.*)$/;
next if ($name =~ /\^\173/);
if ($name eq "HEAD") {
open O, ">", "$git_dir/REMOTE_HEAD";
print O "$sha1\n";
close O;
next;
}
if ($name =~ s/^refs\/heads\///) {
store($sha1, $name, $branch_top);
next;
}
if ($name =~ s/^refs\/tags\///) {
store($sha1, $name, $tag_top);
next;
}
}
close FH;
'
quiet=
local=no
use_local=no
@@ -165,7 +123,7 @@ while
shift
upload_pack="--upload-pack=$1" ;;
*,--upload-pack=*)
upload_pack=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)') ;;
upload_pack=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
1,--depth) usage;;
*,--depth)
shift
@@ -332,8 +290,29 @@ test -d "$GIT_DIR/refs/reference-tmp" && rm -fr "$GIT_DIR/refs/reference-tmp"
if test -f "$GIT_DIR/CLONE_HEAD"
then
# Read git-fetch-pack -k output and store the remote branches.
@@PERL@@ -e "$copy_refs" "$GIT_DIR" "$use_separate_remote" "$origin" ||
exit
if [ -n "$use_separate_remote" ]
then
branch_top="remotes/$origin"
else
branch_top="heads"
fi
tag_top="tags"
while read sha1 name
do
case "$name" in
*'^{}')
continue ;;
HEAD)
destname="REMOTE_HEAD" ;;
refs/heads/*)
destname="refs/$branch_top/${name#refs/heads/}" ;;
refs/tags/*)
destname="refs/$tag_top/${name#refs/tags/}" ;;
*)
continue ;;
esac
git-update-ref -m "clone: from $repo" "$destname" "$sha1" ""
done < "$GIT_DIR/CLONE_HEAD"
fi
cd "$D" || exit

View File

@@ -442,8 +442,11 @@ fi | git-stripspace >"$GIT_DIR"/COMMIT_EDITMSG
case "$signoff" in
t)
need_blank_before_signoff=
tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
grep 'Signed-off-by:' >/dev/null || need_blank_before_signoff=yes
{
echo
test -z "$need_blank_before_signoff" || echo
git-var GIT_COMMITTER_IDENT | sed -e '
s/>.*/>/
s/^/Signed-off-by: /

View File

@@ -37,7 +37,7 @@ do
;;
--upl=*|--uplo=*|--uploa=*|--upload=*|\
--upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)')
exec=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)')
shift
;;
-f|--f|--fo|--for|--forc|--force)

View File

@@ -27,7 +27,7 @@ do
shift;;
-u=*|--u=*|--up=*|--upl=*|--uplo=*|--uploa=*|--upload=*|\
--upload-=*|--upload-p=*|--upload-pa=*|--upload-pac=*|--upload-pack=*)
exec=--upload-pack=$(expr "$1" : '-[^=]*=\(.*\)')
exec=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)')
shift;;
--)
shift; break ;;

View File

@@ -183,7 +183,7 @@ canon_refs_list_for_fetch () {
done
fi
case "$remote" in
'') remote=HEAD ;;
'' | HEAD ) remote=HEAD ;;
refs/heads/* | refs/tags/* | refs/remotes/*) ;;
heads/* | tags/* | remotes/* ) remote="refs/$remote" ;;
*) remote="refs/heads/$remote" ;;

View File

@@ -249,7 +249,8 @@ fi
git-update-index --refresh || exit
diff=$(git-diff-index --cached --name-status -r HEAD)
case "$diff" in
?*) echo "$diff"
?*) echo "cannot rebase: your index is not up-to-date"
echo "$diff"
exit 1
;;
esac

View File

@@ -408,7 +408,7 @@ sub unquote_rfc2047 {
s/_/ /g;
s/=([0-9A-F]{2})/chr(hex($1))/eg;
}
return "$_ - unquoted";
return "$_";
}
sub send_message

View File

@@ -113,8 +113,9 @@ object=$(git-rev-parse --verify --default HEAD "$@") || exit 1
type=$(git-cat-file -t $object) || exit 1
tagger=$(git-var GIT_COMMITTER_IDENT) || exit 1
keyid=$(git-repo-config user.signingkey) ||
keyid=$(expr "z$tagger" : 'z\(.*>\)')
test -n "$username" ||
username=$(git-repo-config user.signingkey) ||
username=$(expr "z$tagger" : 'z\(.*>\)')
trap 'rm -f "$GIT_DIR"/TAG_TMP* "$GIT_DIR"/TAG_FINALMSG "$GIT_DIR"/TAG_EDITMSG' 0
@@ -141,7 +142,7 @@ if [ "$annotate" ]; then
cat "$GIT_DIR"/TAG_FINALMSG ) >"$GIT_DIR"/TAG_TMP
rm -f "$GIT_DIR"/TAG_TMP.asc "$GIT_DIR"/TAG_FINALMSG
if [ "$signed" ]; then
gpg -bsa -u "$keyid" "$GIT_DIR"/TAG_TMP &&
gpg -bsa -u "$username" "$GIT_DIR"/TAG_TMP &&
cat "$GIT_DIR"/TAG_TMP.asc >>"$GIT_DIR"/TAG_TMP ||
die "failed to sign the tag with GPG."
fi

2
git.c
View File

@@ -239,6 +239,8 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
{ "for-each-ref", cmd_for_each_ref, RUN_SETUP },
{ "format-patch", cmd_format_patch, RUN_SETUP },
{ "fsck", cmd_fsck, RUN_SETUP },
{ "fsck-objects", cmd_fsck, RUN_SETUP },
{ "get-tar-commit-id", cmd_get_tar_commit_id },
{ "grep", cmd_grep, RUN_SETUP },
{ "help", cmd_help },

2
refs.c
View File

@@ -663,6 +663,8 @@ struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1)
{
if (check_ref_format(ref) == -1)
return NULL;
return lock_ref_sha1_basic(ref, old_sha1, NULL);
}

View File

@@ -10,6 +10,8 @@ static FILE *info_ref_fp;
static int add_info_ref(const char *path, const unsigned char *sha1, int flag, void *cb_data)
{
struct object *o = parse_object(sha1);
if (!o)
return -1;
fprintf(info_ref_fp, "%s %s\n", sha1_to_hex(sha1), path);
if (o->type == OBJ_TAG) {

View File

@@ -169,19 +169,19 @@ test_expect_success \
test "$(echo $(sort "G g/CVS/Entries"|cut -d/ -f2,3,5))" = "with spaces.png/1.2/-kb with spaces.txt/1.2/"
)'
# This test contains ISO-8859-1 characters
# This test contains UTF-8 characters
test_expect_success \
'File with non-ascii file name' \
'mkdir -p <EFBFBD>/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/<EFBFBD>/<2F>/<2F> &&
echo Foo ><EFBFBD>/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/<EFBFBD>/<2F>/<2F>/g<EFBFBD>rdets<EFBFBD>g<EFBFBD>rdet.txt &&
git add <EFBFBD>/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/<EFBFBD>/<2F>/<2F>/g<EFBFBD>rdets<EFBFBD>g<EFBFBD>rdet.txt &&
cp ../test9200a.png <EFBFBD>/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/<EFBFBD>/<2F>/<2F>/g<EFBFBD>rdets<EFBFBD>g<EFBFBD>rdet.png &&
git add <EFBFBD>/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/<EFBFBD>/<2F>/<2F>/g<EFBFBD>rdets<EFBFBD>g<EFBFBD>rdet.png &&
git commit -a -m "G<EFBFBD>r det s<EFBFBD> g<EFBFBD>r det" && \
'mkdir -p Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö &&
echo Foo >Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.txt &&
cp ../test9200a.png Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
git add Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/gårdetsågårdet.png &&
git commit -a -m "Går det så går det" && \
id=$(git rev-list --max-count=1 HEAD) &&
(cd "$CVSWORK" &&
git-cvsexportcommit -v -c $id &&
test "$(echo $(sort <EFBFBD>/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/<EFBFBD>/<2F>/<2F>/CVS/Entries|cut -d/ -f2,3,5))" = "g<EFBFBD>rdets<EFBFBD>g<EFBFBD>rdet.png/1.1/-kb g<EFBFBD>rdets<EFBFBD>g<EFBFBD>rdet.txt/1.1/"
test "$(echo $(sort Å/goo/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/å/ä/ö/CVS/Entries|cut -d/ -f2,3,5))" = "gårdetsågårdet.png/1.1/-kb gårdetsågårdet.txt/1.1/"
)'
test_expect_success \
@@ -197,6 +197,10 @@ test_expect_success \
! git-cvsexportcommit -c $id
)'
case "$(git repo-config --bool core.filemode)" in
false)
;;
*)
test_expect_success \
'Retain execute bit' \
'mkdir G &&
@@ -211,5 +215,7 @@ test_expect_success \
test -x G/on &&
! test -x G/off
)'
;;
esac
test_done