summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt24
-rw-r--r--Documentation/git-branch.txt9
-rw-r--r--Documentation/git-clone.txt6
-rw-r--r--Documentation/git-svn.txt87
-rw-r--r--Documentation/git-svnimport.txt10
-rw-r--r--Documentation/git-tag.txt7
-rw-r--r--Documentation/tutorial.txt51
-rw-r--r--Makefile4
-rw-r--r--archive-tar.c7
-rw-r--r--builtin-branch.c85
-rw-r--r--builtin-prune.c2
-rw-r--r--builtin-rerere.c7
-rw-r--r--cache.h1
-rw-r--r--commit.c5
-rw-r--r--contrib/emacs/git.el21
-rw-r--r--diff-lib.c9
-rw-r--r--diff.c6
-rw-r--r--diff.h4
-rw-r--r--diffcore.h4
-rwxr-xr-xgenerate-cmdlist.sh1
-rwxr-xr-xgit-clean.sh4
-rwxr-xr-xgit-instaweb.sh3
-rwxr-xr-xgit-remote.perl277
-rwxr-xr-xgit-reset.sh6
-rwxr-xr-xgit-svn.perl90
-rwxr-xr-xgit-svnimport.perl36
-rwxr-xr-xgit-tag.sh11
-rwxr-xr-xgit-verify-tag.sh3
-rwxr-xr-xgitweb/gitweb.perl41
-rw-r--r--lockfile.c9
-rw-r--r--pack-check.c20
-rw-r--r--refs.c1
-rwxr-xr-xt/test-lib.sh6
-rw-r--r--tree-walk.c1
34 files changed, 646 insertions, 212 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2f4fc25258..4318bf9334 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -145,6 +145,21 @@ branch.<name>.merge::
this option, `git pull` defaults to merge the first refspec fetched.
Specify multiple values to get an octopus merge.
+color.branch::
+ A boolean to enable/disable color in the output of
+ gitlink:git-branch[1]. May be set to `true` (or `always`),
+ `false` (or `never`) or `auto`, in which case colors are used
+ only when the output is to a terminal. Defaults to false.
+
+color.branch.<slot>::
+ Use customized color for branch coloration. `<slot>` is one of
+ `current` (the current branch), `local` (a local branch),
+ `remote` (a tracking branch in refs/remotes/), `plain` (other
+ refs), or `reset` (the normal terminal color). The value for
+ these configuration variables can be one of: `normal`, `bold`,
+ `dim`, `ul`, `blink`, `reverse`, `reset`, `black`, `red`,
+ `green`, `yellow`, `blue`, `magenta`, `cyan`, or `white`.
+
color.diff::
When true (or `always`), always use colors in patch.
When false (or `never`), never. When set to `auto`, use
@@ -155,11 +170,8 @@ color.diff.<slot>::
specifies which part of the patch to use the specified
color, and is one of `plain` (context text), `meta`
(metainformation), `frag` (hunk header), `old` (removed
- lines), or `new` (added lines). The value for these
- configuration variables can be one of: `normal`, `bold`,
- `dim`, `ul`, `blink`, `reverse`, `reset`, `black`,
- `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, or
- `white`.
+ lines), or `new` (added lines). The values of these
+ variables may be specified as in color.branch.<slot>.
color.pager::
A boolean to enable/disable colored output when the pager is in
@@ -177,7 +189,7 @@ color.status.<slot>::
`added` or `updated` (files which are added but not committed),
`changed` (files which are changed but not added in the index),
or `untracked` (files which are not tracked by git). The values of
- these variables may be specified as in color.diff.<slot>.
+ these variables may be specified as in color.branch.<slot>.
diff.renameLimit::
The number of files to consider when performing the copy/rename
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index c464bd2fda..e872fc89fc 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -8,7 +8,7 @@ git-branch - List, create, or delete branches.
SYNOPSIS
--------
[verse]
-'git-branch' [-r | -a] [-v [--abbrev=<length>]]
+'git-branch' [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]
'git-branch' [-l] [-f] <branchname> [<start-point>]
'git-branch' (-m | -M) [<oldbranch>] <newbranch>
'git-branch' (-d | -D) [-r] <branchname>...
@@ -60,6 +60,13 @@ OPTIONS
-M::
Move/rename a branch even if the new branchname already exists.
+--color::
+ Color branches to highlight current, local, and remote branches.
+
+--no-color::
+ Turn off branch colors, even when the configuration file gives the
+ default to color output.
+
-r::
List or delete (if used with -d) the remote-tracking branches.
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index e7085fdf5f..a78207461d 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -18,13 +18,13 @@ DESCRIPTION
Clones a repository into a newly created directory, creates
remote-tracking branches for each branch in the cloned repository
-(visible using `git branch -r`), and creates and checks out a master
-branch equal to the cloned repository's master branch.
+(visible using `git branch -r`), and creates and checks out an initial
+branch equal to the cloned repository's currently active branch.
After the clone, a plain `git fetch` without arguments will update
all the remote-tracking branches, and a `git pull` without
arguments will in addition merge the remote master branch into the
-current branch.
+current master branch, if any.
This default configuration is achieved by creating references to
the remote branch heads under `$GIT_DIR/refs/remotes/origin` and
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index f5f57e8f87..ce63defffd 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -3,7 +3,7 @@ git-svn(1)
NAME
----
-git-svn - bidirectional operation between a single Subversion branch and git
+git-svn - bidirectional operation between Subversion and git
SYNOPSIS
--------
@@ -11,24 +11,20 @@ SYNOPSIS
DESCRIPTION
-----------
-git-svn is a simple conduit for changesets between a single Subversion
-branch and git. It is not to be confused with gitlink:git-svnimport[1].
-They were designed with very different goals in mind.
+git-svn is a simple conduit for changesets between Subversion and git.
+It is not to be confused with gitlink:git-svnimport[1], which is
+read-only and geared towards tracking multiple branches.
-git-svn is designed for an individual developer who wants a
+git-svn was originally designed for an individual developer who wants a
bidirectional flow of changesets between a single branch in Subversion
-and an arbitrary number of branches in git. git-svnimport is designed
-for read-only operation on repositories that match a particular layout
-(albeit the recommended one by SVN developers).
+and an arbitrary number of branches in git. Since its inception,
+git-svn has gained the ability to track multiple branches in a manner
+similar to git-svnimport; but it cannot (yet) automatically detect new
+branches and tags like git-svnimport does.
-For importing svn, git-svnimport is potentially more powerful when
-operating on repositories organized under the recommended
-trunk/branch/tags structure, and should be faster, too.
-
-git-svn mostly ignores the very limited view of branching that
-Subversion has. This allows git-svn to be much easier to use,
-especially on repositories that are not organized in a manner that
-git-svnimport is designed for.
+git-svn is especially useful when it comes to tracking repositories
+not organized in the way Subversion developers recommend (trunk,
+branches, tags directories).
COMMANDS
--------
@@ -57,11 +53,13 @@ See '<<fetch-args,Additional Fetch Arguments>>' if you are interested in
manually joining branches on commit.
'dcommit'::
- Commit all diffs from a specified head directly to the SVN
+ Commit each diff from a specified head directly to the SVN
repository, and then rebase or reset (depending on whether or
- not there is a diff between SVN and head). It is recommended
- that you run git-svn fetch and rebase (not pull) your commits
- against the latest changes in the SVN repository.
+ not there is a diff between SVN and head). This will create
+ a revision in SVN for each commit in git.
+ It is recommended that you run git-svn fetch and rebase (not
+ pull or merge) your commits against the latest changes in the
+ SVN repository.
An optional command-line argument may be specified as an
alternative to HEAD.
This is advantageous over 'set-tree' (below) because it produces
@@ -370,7 +368,7 @@ SVN was very wrong.
Basic Examples
~~~~~~~~~~~~~~
-Tracking and contributing to a Subversion-managed project:
+Tracking and contributing to a the trunk of a Subversion-managed project:
------------------------------------------------------------------------
# Initialize a repo (like git init-db):
@@ -388,19 +386,44 @@ Tracking and contributing to a Subversion-managed project:
git-svn show-ignore >> .git/info/exclude
------------------------------------------------------------------------
-REBASE VS. PULL
----------------
+Tracking and contributing to an entire Subversion-managed project
+(complete with a trunk, tags and branches):
+See also:
+'<<tracking-multiple-repos,Tracking Multiple Repositories or Branches>>'
+
+------------------------------------------------------------------------
+# Initialize a repo (like git init-db):
+ git-svn multi-init http://svn.foo.org/project \
+ -T trunk -b branches -t tags
+# Fetch remote revisions:
+ git-svn multi-fetch
+# Create your own branch of trunk to hack on:
+ git checkout -b my-trunk remotes/trunk
+# Do some work, and then commit your new changes to SVN, as well as
+# automatically updating your working HEAD:
+ git-svn dcommit -i trunk
+# Something has been committed to trunk, rebase the latest into your branch:
+ git-svn multi-fetch && git rebase remotes/trunk
+# Append svn:ignore settings of trunk to the default git exclude file:
+ git-svn show-ignore -i trunk >> .git/info/exclude
+# Check for new branches and tags (no arguments are needed):
+ git-svn multi-init
+------------------------------------------------------------------------
+
+REBASE VS. PULL/MERGE
+---------------------
Originally, git-svn recommended that the remotes/git-svn branch be
-pulled from. This is because the author favored 'git-svn set-tree B'
-to commit a single head rather than the 'git-svn set-tree A..B' notation
-to commit multiple commits.
-
-If you use 'git-svn set-tree A..B' to commit several diffs and you do not
-have the latest remotes/git-svn merged into my-branch, you should use
-'git rebase' to update your work branch instead of 'git pull'. 'pull'
-can cause non-linear history to be flattened when committing into SVN,
-which can lead to merge commits reversing previous commits in SVN.
+pulled or merged from. This is because the author favored
+'git-svn set-tree B' to commit a single head rather than the
+'git-svn set-tree A..B' notation to commit multiple commits.
+
+If you use 'git-svn set-tree A..B' to commit several diffs and you do
+not have the latest remotes/git-svn merged into my-branch, you should
+use 'git rebase' to update your work branch instead of 'git pull' or
+'git merge'. 'pull/merge' can cause non-linear history to be flattened
+when committing into SVN, which can lead to merge commits reversing
+previous commits in SVN.
DESIGN PHILOSOPHY
-----------------
diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt
index 2c7c7dad54..b166cf3327 100644
--- a/Documentation/git-svnimport.txt
+++ b/Documentation/git-svnimport.txt
@@ -15,7 +15,7 @@ SYNOPSIS
[ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ]
[ -s start_chg ] [ -m ] [ -r ] [ -M regex ]
[ -I <ignorefile_name> ] [ -A <author_file> ]
- [ -P <path_from_trunk> ]
+ [ -R <repack_each_revs>] [ -P <path_from_trunk> ]
<SVN_repository_URL> [ <path> ]
@@ -108,6 +108,14 @@ repository without -A.
Formerly, this option controlled how many revisions to pull,
due to SVN memory leaks. (These have been worked around.)
+-R <repack_each_revs>::
+ Specify how often git repository should be repacked.
++
+The default value is 1000. git-svnimport will do import in chunks of 1000
+revisions, after each chunk git repository will be repacked. To disable
+this behavior specify some big value here which is mote than number of
+revisions to import.
+
-P <path_from_trunk>::
Partial import of the SVN tree.
+
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 48b82b86f8..80bece0775 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -9,7 +9,7 @@ git-tag - Create a tag object signed with GPG
SYNOPSIS
--------
[verse]
-'git-tag' [-a | -s | -u <key-id>] [-f | -d] [-m <msg> | -F <file>]
+'git-tag' [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg> | -F <file>]
<name> [<head>]
'git-tag' -l [<pattern>]
@@ -35,6 +35,8 @@ GnuPG key for signing.
`-d <tag>` deletes the tag.
+`-v <tag>` verifies the gpg signature of the tag.
+
`-l <pattern>` lists tags that match the given pattern (or all
if no pattern is given).
@@ -55,6 +57,9 @@ OPTIONS
-d::
Delete an existing tag with the given name
+-v::
+ Verify the gpg signature of given the tag
+
-l <pattern>::
List tags that match the given pattern (or all if no pattern is given).
diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt
index d043e844d2..01d4a47a97 100644
--- a/Documentation/tutorial.txt
+++ b/Documentation/tutorial.txt
@@ -43,8 +43,7 @@ Initialized empty Git repository in .git/
You've now initialized the working directory--you may notice a new
directory created, named ".git". Tell git that you want it to track
-every file under the current directory with (notice the dot '.'
-that means the current directory):
+every file under the current directory (note the '.') with:
------------------------------------------------
$ git add .
@@ -59,32 +58,40 @@ $ git commit
will prompt you for a commit message, then record the current state
of all the files to the repository.
+Making changes
+--------------
+
Try modifying some files, then run
------------------------------------------------
$ git diff
------------------------------------------------
-to review your changes. When you're done,
+to review your changes. When you're done, tell git that you
+want the updated contents of these files in the commit and then
+make a commit, like this:
------------------------------------------------
-$ git commit file1 file2...
+$ git add file1 file2 file3
+$ git commit
------------------------------------------------
-will again prompt your for a message describing the change, and then
-record the new versions of the files you listed. It is cumbersome
-to list all files and you can say `-a` (which stands for 'all')
-instead.
+This will again prompt your for a message describing the change, and then
+record the new versions of the files you listed.
+
+Alternatively, instead of running `git add` beforehand, you can use
------------------------------------------------
$ git commit -a
------------------------------------------------
+which will automatically notice modified (but not new) files.
+
A note on commit messages: Though not required, it's a good idea to
begin the commit message with a single short (less than 50 character)
line summarizing the change, followed by a blank line and then a more
thorough description. Tools that turn commits into email, for
-example, use the first line on the Subject line and the rest of the
+example, use the first line on the Subject: line and the rest of the
commit in the body.
@@ -142,6 +149,13 @@ If you also want to see complete diffs at each step, use
$ git log -p
------------------------------------------------
+Often the overview of the change is useful to get a feel of
+each step
+
+------------------------------------------------
+$ git log --stat --summary
+------------------------------------------------
+
Managing branches
-----------------
@@ -222,6 +236,15 @@ $ gitk
will show a nice graphical representation of the resulting history.
+At this point you could delete the experimental branch with
+
+------------------------------------------------
+$ git branch -d experimental
+------------------------------------------------
+
+This command ensures that the changes in the experimental branch are
+already in the current branch.
+
If you develop on a branch crazy-idea, then regret it, you can always
delete the branch with
@@ -381,7 +404,7 @@ commit.
$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
-------------------------------------
-But there other ways to refer to commits. You can use any initial
+But there are other ways to refer to commits. You can use any initial
part of the name that is long enough to uniquely identify the commit:
-------------------------------------
@@ -391,8 +414,8 @@ $ git show HEAD # the tip of the current branch
$ git show experimental # the tip of the "experimental" branch
-------------------------------------
-Every commit has at least one "parent" commit, which points to the
-previous state of the project:
+Every commit usually has one "parent" commit
+which points to the previous state of the project:
-------------------------------------
$ git show HEAD^ # to see the parent of HEAD
@@ -510,10 +533,10 @@ of the file:
$ git diff v2.5:Makefile HEAD:Makefile.in
-------------------------------------
-You can also use "git cat-file -p" to see any such file:
+You can also use "git show" to see any such file:
-------------------------------------
-$ git cat-file -p v2.5:Makefile
+$ git show v2.5:Makefile
-------------------------------------
Next Steps
diff --git a/Makefile b/Makefile
index fa1a02289c..5c712b94c1 100644
--- a/Makefile
+++ b/Makefile
@@ -179,7 +179,7 @@ SCRIPT_SH = \
SCRIPT_PERL = \
git-add--interactive.perl \
git-archimport.perl git-cvsimport.perl git-relink.perl \
- git-cvsserver.perl \
+ git-cvsserver.perl git-remote.perl \
git-svnimport.perl git-cvsexportcommit.perl \
git-send-email.perl git-svn.perl
@@ -818,7 +818,7 @@ test-sha1$X: test-sha1.o $(GITLIBS)
check-sha1:: test-sha1$X
./test-sha1.sh
-check:
+check: common-cmds.h
for i in *.c; do sparse $(ALL_CFLAGS) $(SPARSE_FLAGS) $$i || exit; done
diff --git a/archive-tar.c b/archive-tar.c
index af47fdc955..7d52a061f4 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -15,7 +15,7 @@ static char block[BLOCKSIZE];
static unsigned long offset;
static time_t archive_time;
-static int tar_umask;
+static int tar_umask = 002;
static int verbose;
/* writes out the whole block, but only if it is full */
@@ -210,11 +210,10 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
sprintf(header.size, "%011lo", S_ISREG(mode) ? size : 0);
sprintf(header.mtime, "%011lo", archive_time);
- /* XXX: should we provide more meaningful info here? */
sprintf(header.uid, "%07o", 0);
sprintf(header.gid, "%07o", 0);
- strlcpy(header.uname, "git", sizeof(header.uname));
- strlcpy(header.gname, "git", sizeof(header.gname));
+ strlcpy(header.uname, "root", sizeof(header.uname));
+ strlcpy(header.gname, "root", sizeof(header.gname));
sprintf(header.devmajor, "%07o", 0);
sprintf(header.devminor, "%07o", 0);
diff --git a/builtin-branch.c b/builtin-branch.c
index 745ee04d6e..d3df5a57f1 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -12,7 +12,7 @@
#include "builtin.h"
static const char builtin_branch_usage[] =
- "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [-r | -a] [-v [--abbrev=<length>]]";
+ "git-branch [-r] (-d | -D) <branchname> | [-l] [-f] <branchname> [<start-point>] | (-m | -M) [<oldbranch>] <newbranch> | [--color | --no-color] [-r | -a] [-v [--abbrev=<length>]]";
#define REF_UNKNOWN_TYPE 0x00
#define REF_LOCAL_BRANCH 0x01
@@ -231,29 +231,54 @@ static int ref_cmp(const void *r1, const void *r2)
return strcmp(c1->name, c2->name);
}
-static void print_ref_info(const unsigned char *sha1, int abbrev)
+static void print_ref_item(struct ref_item *item, int maxwidth, int verbose,
+ int abbrev, int current)
{
+ char c;
+ int color;
struct commit *commit;
char subject[256];
+ switch (item->kind) {
+ case REF_LOCAL_BRANCH:
+ color = COLOR_BRANCH_LOCAL;
+ break;
+ case REF_REMOTE_BRANCH:
+ color = COLOR_BRANCH_REMOTE;
+ break;
+ default:
+ color = COLOR_BRANCH_PLAIN;
+ break;
+ }
- commit = lookup_commit(sha1);
- if (commit && !parse_commit(commit))
- pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
- subject, sizeof(subject), 0,
- NULL, NULL, 0);
- else
- strcpy(subject, " **** invalid ref ****");
+ c = ' ';
+ if (current) {
+ c = '*';
+ color = COLOR_BRANCH_CURRENT;
+ }
- printf(" %s %s\n", find_unique_abbrev(sha1, abbrev), subject);
+ if (verbose) {
+ commit = lookup_commit(item->sha1);
+ if (commit && !parse_commit(commit))
+ pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
+ subject, sizeof(subject), 0,
+ NULL, NULL, 0);
+ else
+ strcpy(subject, " **** invalid ref ****");
+ printf("%c %s%-*s%s %s %s\n", c, branch_get_color(color),
+ maxwidth, item->name,
+ branch_get_color(COLOR_BRANCH_RESET),
+ find_unique_abbrev(item->sha1, abbrev), subject);
+ } else {
+ printf("%c %s%s%s\n", c, branch_get_color(color), item->name,
+ branch_get_color(COLOR_BRANCH_RESET));
+ }
}
static void print_ref_list(int kinds, int verbose, int abbrev)
{
int i;
- char c;
struct ref_list ref_list;
- int color;
memset(&ref_list, 0, sizeof(ref_list));
ref_list.kinds = kinds;
@@ -262,38 +287,10 @@ static void print_ref_list(int kinds, int verbose, int abbrev)
qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp);
for (i = 0; i < ref_list.index; i++) {
- switch( ref_list.list[i].kind ) {
- case REF_LOCAL_BRANCH:
- color = COLOR_BRANCH_LOCAL;
- break;
- case REF_REMOTE_BRANCH:
- color = COLOR_BRANCH_REMOTE;
- break;
- default:
- color = COLOR_BRANCH_PLAIN;
- break;
- }
-
- c = ' ';
- if (ref_list.list[i].kind == REF_LOCAL_BRANCH &&
- !strcmp(ref_list.list[i].name, head)) {
- c = '*';
- color = COLOR_BRANCH_CURRENT;
- }
-
- if (verbose) {
- printf("%c %s%-*s%s", c,
- branch_get_color(color),
- ref_list.maxwidth,
- ref_list.list[i].name,
- branch_get_color(COLOR_BRANCH_RESET));
- print_ref_info(ref_list.list[i].sha1, abbrev);
- }
- else
- printf("%c %s%s%s\n", c,
- branch_get_color(color),
- ref_list.list[i].name,
- branch_get_color(COLOR_BRANCH_RESET));
+ int current = (ref_list.list[i].kind == REF_LOCAL_BRANCH) &&
+ !strcmp(ref_list.list[i].name, head);
+ print_ref_item(&ref_list.list[i], ref_list.maxwidth, verbose,
+ abbrev, current);
}
free_ref_list(&ref_list);
diff --git a/builtin-prune.c b/builtin-prune.c
index 00a53b3647..b469c43bc5 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -253,6 +253,8 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
usage(prune_usage);
}
+ save_commit_buffer = 0;
+
/*
* Set up revision parsing, and mark us as being interested
* in all object types, not just commits.
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 7442498dee..079c0bdf36 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -350,11 +350,10 @@ static int do_plain_rerere(struct path_list *rr, int fd)
fprintf(stderr, "Recorded resolution for '%s'.\n", path);
copy_file(path, rr_path(name, "postimage"));
tail_optimization:
- if (i < rr->nr - 1) {
+ if (i < rr->nr - 1)
memmove(rr->items + i,
- rr->items + i + 1,
- rr->nr - i - 1);
- }
+ rr->items + i + 1,
+ sizeof(rr->items[0]) * (rr->nr - i - 1));
rr->nr--;
i--;
}
diff --git a/cache.h b/cache.h
index 384f829b96..31b0819e83 100644
--- a/cache.h
+++ b/cache.h
@@ -179,6 +179,7 @@ extern int refresh_cache(unsigned int flags);
struct lock_file {
struct lock_file *next;
+ char on_list;
char filename[PATH_MAX];
};
extern int hold_lock_file_for_update(struct lock_file *, const char *path, int);
diff --git a/commit.c b/commit.c
index 544e42629e..2a58175aca 100644
--- a/commit.c
+++ b/commit.c
@@ -703,7 +703,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
const char *after_subject,
int relative_date)
{
- int hdr = 1, body = 0;
+ int hdr = 1, body = 0, seen_title = 0;
unsigned long offset = 0;
int indent = 4;
int parents_shown = 0;
@@ -809,6 +809,8 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
body = 1;
if (is_empty_line(line, &linelen)) {
+ if (!seen_title)
+ continue;
if (!body)
continue;
if (subject)
@@ -817,6 +819,7 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
break;
}
+ seen_title = 1;
if (subject) {
int slen = strlen(subject);
memcpy(buf + offset, subject, slen);
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index 972c402ea0..ede3ab2bd8 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -49,6 +49,7 @@
(eval-when-compile (require 'cl))
(require 'ewoc)
+(require 'log-edit)
;;;; Customizations
@@ -147,6 +148,13 @@ if there is already one that displays the same directory."
(defconst git-log-msg-separator "--- log message follows this line ---")
+(defvar git-log-edit-font-lock-keywords
+ `(("^\\(Author:\\|Date:\\|Parent:\\|Signed-off-by:\\)\\(.*\\)$"
+ (1 font-lock-keyword-face)
+ (2 font-lock-function-name-face))
+ (,(concat "^\\(" (regexp-quote git-log-msg-separator) "\\)$")
+ (1 font-lock-comment-face))))
+
(defun git-get-env-strings (env)
"Build a list of NAME=VALUE strings from a list of environment strings."
(mapcar (lambda (entry) (concat (car entry) "=" (cdr entry))) env))
@@ -777,7 +785,7 @@ and returns the process output as a string."
(interactive)
(let ((files (git-marked-files-state 'unmerged)))
(when files
- (apply #'git-run-command nil nil "update-index" "--info-only" "--" (git-get-filenames files))
+ (apply #'git-run-command nil nil "update-index" "--" (git-get-filenames files))
(git-set-files-state files 'modified)
(git-refresh-files))))
@@ -894,14 +902,9 @@ and returns the process output as a string."
(sign-off
(insert (format "\n\nSigned-off-by: %s <%s>\n"
(git-get-committer-name) (git-get-committer-email)))))))
- (let ((log-edit-font-lock-keywords
- `(("^\\(Author:\\|Date:\\|Parent:\\|Signed-off-by:\\)\\(.*\\)"
- (1 font-lock-keyword-face)
- (2 font-lock-function-name-face))
- (,(concat "^\\(" (regexp-quote git-log-msg-separator) "\\)$")
- (1 font-lock-comment-face)))))
- (log-edit #'git-do-commit nil #'git-log-edit-files buffer)
- (re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t))))
+ (log-edit #'git-do-commit nil #'git-log-edit-files buffer)
+ (setq font-lock-keywords (font-lock-compile-keywords git-log-edit-font-lock-keywords))
+ (re-search-forward (regexp-quote (concat git-log-msg-separator "\n")) nil t)))
(defun git-find-file ()
"Visit the current file in its own buffer."
diff --git a/diff-lib.c b/diff-lib.c
index fc69fb92a5..2c9be60ed9 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -97,7 +97,7 @@ int run_diff_files(struct rev_info *revs, int silent_on_removed)
* Show the diff for the 'ce' if we found the one
* from the desired stage.
*/
- diff_unmerge(&revs->diffopt, ce->name);
+ diff_unmerge(&revs->diffopt, ce->name, 0, null_sha1);
if (ce_stage(ce) != diff_unmerged_stage)
continue;
}
@@ -297,9 +297,12 @@ static int diff_cache(struct rev_info *revs,
!show_modified(revs, ce, ac[1], 0,
cached, match_missing))
break;
- /* fallthru */
+ diff_unmerge(&revs->diffopt, ce->name,
+ ntohl(ce->ce_mode), ce->sha1);
+ break;
case 3:
- diff_unmerge(&revs->diffopt, ce->name);
+ diff_unmerge(&revs->diffopt, ce->name,
+ 0, null_sha1);
break;
default:
diff --git a/diff.c b/diff.c
index f14288bb8a..2c2e9dcb8c 100644
--- a/diff.c
+++ b/diff.c
@@ -2875,10 +2875,12 @@ void diff_change(struct diff_options *options,
}
void diff_unmerge(struct diff_options *options,
- const char *path)
+ const char *path,
+ unsigned mode, const unsigned char *sha1)
{
struct diff_filespec *one, *two;
one = alloc_filespec(path);
two = alloc_filespec(path);
- diff_queue(&diff_queued_diff, one, two);
+ fill_filespec(one, sha1, mode);
+ diff_queue(&diff_queued_diff, one, two)->is_unmerged = 1;
}
diff --git a/diff.h b/diff.h
index eff445596d..7a347cf77d 100644
--- a/diff.h
+++ b/diff.h
@@ -144,7 +144,9 @@ extern void diff_change(struct diff_options *,
const char *base, const char *path);
extern void diff_unmerge(struct diff_options *,
- const char *path);
+ const char *path,
+ unsigned mode,
+ const unsigned char *sha1);
extern int diff_scoreopt_parse(const char *opt);
diff --git a/diffcore.h b/diffcore.h
index 2249bc2c05..1ea80671e3 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -54,9 +54,9 @@ struct diff_filepair {
unsigned source_stays : 1; /* all of R/C are copies */
unsigned broken_pair : 1;
unsigned renamed_pair : 1;
+ unsigned is_unmerged : 1;
};
-#define DIFF_PAIR_UNMERGED(p) \
- (!DIFF_FILE_VALID((p)->one) && !DIFF_FILE_VALID((p)->two))
+#define DIFF_PAIR_UNMERGED(p) ((p)->is_unmerged)
#define DIFF_PAIR_RENAME(p) ((p)->renamed_pair)
diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index 06c42b042d..1de14ea82f 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -37,7 +37,6 @@ show
show-branch
status
tag
-verify-tag
EOF
while read cmd
do
diff --git a/git-clean.sh b/git-clean.sh
index 3834323bcf..071b974f49 100755
--- a/git-clean.sh
+++ b/git-clean.sh
@@ -18,7 +18,6 @@ SUBDIRECTORY_OK=Yes
ignored=
ignoredonly=
cleandir=
-quiet=
rmf="rm -f --"
rmrf="rm -rf --"
rm_refuse="echo Not removing"
@@ -31,14 +30,13 @@ do
cleandir=1
;;
-n)
- quiet=1
rmf="echo Would remove"
rmrf="echo Would remove"
rm_refuse="echo Would not remove"
echo1=":"
;;
-q)
- quiet=1
+ echo1=":"
;;
-x)
ignored=1
diff --git a/git-instaweb.sh b/git-instaweb.sh
index 08362f43c0..80adc8307b 100755
--- a/git-instaweb.sh
+++ b/git-instaweb.sh
@@ -53,6 +53,9 @@ start_httpd () {
return
fi
done
+ echo "$httpd_only not found. Install $httpd_only or use" \
+ "--httpd to specify another http daemon."
+ exit 1
fi
if test $? != 0; then
echo "Could not execute http daemon $httpd."
diff --git a/git-remote.perl b/git-remote.perl
new file mode 100755
index 0000000000..059c141b68
--- /dev/null
+++ b/git-remote.perl
@@ -0,0 +1,277 @@
+#!/usr/bin/perl -w
+
+use Git;
+my $git = Git->repository();
+
+sub add_remote_config {
+ my ($hash, $name, $what, $value) = @_;
+ if ($what eq 'url') {
+ if (exists $hash->{$name}{'URL'}) {
+ print STDERR "Warning: more than one remote.$name.url\n";
+ }
+ $hash->{$name}{'URL'} = $value;
+ }
+ elsif ($what eq 'fetch') {
+ $hash->{$name}{'FETCH'} ||= [];
+ push @{$hash->{$name}{'FETCH'}}, $value;
+ }
+ if (!exists $hash->{$name}{'SOURCE'}) {
+ $hash->{$name}{'SOURCE'} = 'config';
+ }
+}
+
+sub add_remote_remotes {
+ my ($hash, $file, $name) = @_;
+
+ if (exists $hash->{$name}) {
+ $hash->{$name}{'WARNING'} = 'ignored due to config';
+ return;
+ }
+
+ my $fh;
+ if (!open($fh, '<', $file)) {
+ print STDERR "Warning: cannot open $file\n";
+ return;
+ }
+ my $it = { 'SOURCE' => 'remotes' };
+ $hash->{$name} = $it;
+ while (<$fh>) {
+ chomp;
+ if (/^URL:\s*(.*)$/) {
+ # Having more than one is Ok -- it is used for push.
+ if (! exists $it->{'URL'}) {
+ $it->{'URL'} = $1;
+ }
+ }
+ elsif (/^Push:\s*(.*)$/) {
+ ; # later
+ }
+ elsif (/^Pull:\s*(.*)$/) {
+ $it->{'FETCH'} ||= [];
+ push @{$it->{'FETCH'}}, $1;
+ }
+ elsif (/^\#/) {
+ ; # ignore
+ }
+ else {
+ print STDERR "Warning: funny line in $file: $_\n";
+ }
+ }
+ close($fh);
+}
+
+sub list_remote {
+ my ($git) = @_;
+ my %seen = ();
+ my @remotes = eval {
+ $git->command(qw(repo-config --get-regexp), '^remote\.');
+ };
+ for (@remotes) {
+ if (/^remote\.([^.]*)\.(\S*)\s+(.*)$/) {
+ add_remote_config(\%seen, $1, $2, $3);
+ }
+ }
+
+ my $dir = $git->repo_path() . "/remotes";
+ if (opendir(my $dh, $dir)) {
+ local $_;
+ while ($_ = readdir($dh)) {
+ chomp;
+ next if (! -f "$dir/$_" || ! -r _);
+ add_remote_remotes(\%seen, "$dir/$_", $_);
+ }
+ }
+
+ return \%seen;
+}
+
+sub add_branch_config {
+ my ($hash, $name, $what, $value) = @_;
+ if ($what eq 'remote') {
+ if (exists $hash->{$name}{'REMOTE'}) {
+ print STDERR "Warning: more than one branch.$name.remote\n";
+ }
+ $hash->{$name}{'REMOTE'} = $value;
+ }
+ elsif ($what eq 'merge') {
+ $hash->{$name}{'MERGE'} ||= [];
+ push @{$hash->{$name}{'MERGE'}}, $value;
+ }
+}
+
+sub list_branch {
+ my ($git) = @_;
+ my %seen = ();
+ my @branches = eval {
+ $git->command(qw(repo-config --get-regexp), '^branch\.');
+ };
+ for (@branches) {
+ if (/^branch\.([^.]*)\.(\S*)\s+(.*)$/) {
+ add_branch_config(\%seen, $1, $2, $3);
+ }
+ }
+
+ return \%seen;
+}
+
+my $remote = list_remote($git);
+my $branch = list_branch($git);
+
+sub update_ls_remote {
+ my ($harder, $info) = @_;
+
+ return if (($harder == 0) ||
+ (($harder == 1) && exists $info->{'LS_REMOTE'}));
+
+ my @ref = map {
+ s|^[0-9a-f]{40}\s+refs/heads/||;
+ $_;
+ } $git->command(qw(ls-remote --heads), $info->{'URL'});
+ $info->{'LS_REMOTE'} = \@ref;
+}
+
+sub show_wildcard_mapping {
+ my ($forced, $ours, $ls) = @_;
+ my %refs;
+ for (@$ls) {
+ $refs{$_} = 01; # bit #0 to say "they have"
+ }
+ for ($git->command('for-each-ref', "refs/remotes/$ours")) {
+ chomp;
+ next unless (s|^[0-9a-f]{40}\s[a-z]+\srefs/remotes/$ours/||);
+ next if ($_ eq 'HEAD');
+ $refs{$_} ||= 0;
+ $refs{$_} |= 02; # bit #1 to say "we have"
+ }
+ my (@new, @stale, @tracked);
+ for (sort keys %refs) {
+ my $have = $refs{$_};
+ if ($have == 1) {
+ push @new, $_;
+ }
+ elsif ($have == 2) {
+ push @stale, $_;
+ }
+ elsif ($have == 3) {
+ push @tracked, $_;
+ }
+ }
+ if (@new) {
+ print " New remote branches (next fetch will store in remotes/$ours)\n";
+ print " @new\n";
+ }
+ if (@stale) {
+ print " Stale tracking branches in remotes/$ours (you'd better remove them)\n";
+ print " @stale\n";
+ }
+ if (@tracked) {
+ print " Tracked remote branches\n";
+ print " @tracked\n";
+ }
+}
+
+sub show_mapping {
+ my ($name, $info) = @_;
+ my $fetch = $info->{'FETCH'};
+ my $ls = $info->{'LS_REMOTE'};
+ my (@stale, @tracked);
+
+ for (@$fetch) {
+ next unless (/(\+)?([^:]+):(.*)/);
+ my ($forced, $theirs, $ours) = ($1, $2, $3);
+ if ($theirs eq 'refs/heads/*' &&
+ $ours =~ /^refs\/remotes\/(.*)\/\*$/) {
+ # wildcard mapping
+ show_wildcard_mapping($forced, $1, $ls);
+ }
+ elsif ($theirs =~ /\*/ || $ours =~ /\*/) {
+ print STDERR "Warning: unrecognized mapping in remotes.$name.fetch: $_\n";
+ }
+ elsif ($theirs =~ s|^refs/heads/||) {
+ if (!grep { $_ eq $theirs } @$ls) {
+ push @stale, $theirs;
+ }
+ elsif ($ours ne '') {
+ push @tracked, $theirs;
+ }
+ }
+ }
+ if (@stale) {
+ print " Stale tracking branches in remotes/$name (you'd better remove them)\n";
+ print " @stale\n";
+ }
+ if (@tracked) {
+ print " Tracked remote branches\n";
+ print " @tracked\n";
+ }
+}
+
+sub show_remote {
+ my ($name, $ls_remote) = @_;
+ if (!exists $remote->{$name}) {
+ print STDERR "No such remote $name\n";
+ return;
+ }
+ my $info = $remote->{$name};
+ update_ls_remote($ls_remote, $info);
+
+ print "* remote $name\n";
+ print " URL: $info->{'URL'}\n";
+ for my $branchname (sort keys %$branch) {
+ next if ($branch->{$branchname}{'REMOTE'} ne $name);
+ my @merged = map {
+ s|^refs/heads/||;
+ $_;
+ } split(' ',"@{$branch->{$branchname}{'MERGE'}}");
+ next unless (@merged);
+ print " Remote branch(es) merged with 'git pull' while on branch $branchname\n";
+ print " @merged\n";
+ }
+ if ($info->{'LS_REMOTE'}) {
+ show_mapping($name, $info);
+ }
+}
+
+sub add_remote {
+ my ($name, $url) = @_;
+ if (exists $remote->{$name}) {
+ print STDERR "remote $name already exists.\n";
+ exit(1);
+ }
+ $git->command('repo-config', "remote.$name.url", $url);
+ $git->command('repo-config', "remote.$name.fetch",
+ "+refs/heads/*:refs/remotes/$name/*");
+}
+
+if (!@ARGV) {
+ for (sort keys %$remote) {
+ print "$_\n";
+ }
+}
+elsif ($ARGV[0] eq 'show') {
+ my $ls_remote = 1;
+ my $i;
+ for ($i = 1; $i < @ARGV; $i++) {
+ if ($ARGV[$i] eq '-n') {
+ $ls_remote = 0;
+ }
+ else {
+ last;
+ }
+ }
+ if ($i >= @ARGV) {
+ print STDERR "Usage: git remote show <remote>\n";
+ exit(1);
+ }
+ for (; $i < @ARGV; $i++) {
+ show_remote($ARGV[$i], $ls_remote);
+ }
+}
+elsif ($ARGV[0] eq 'add') {
+ if (@ARGV != 3) {
+ print STDERR "Usage: git remote add <name> <url>\n";
+ exit(1);
+ }
+ add_remote($ARGV[1], $ARGV[2]);
+}
+
diff --git a/git-reset.sh b/git-reset.sh
index a9693701a3..76c8a818d4 100755
--- a/git-reset.sh
+++ b/git-reset.sh
@@ -44,8 +44,10 @@ if test $# != 0
then
test "$reset_type" == "--mixed" ||
die "Cannot do partial $reset_type reset."
- git ls-tree -r --full-name $rev -- "$@" |
- git update-index --add --index-info || exit
+
+ git-diff-index --cached $rev -- "$@" |
+ sed -e 's/^:\([0-7][0-7]*\) [0-7][0-7]* \([0-9a-f][0-9a-f]*\) [0-9a-f][0-9a-f]* [A-Z] \(.*\)$/\1 \2 \3/' |
+ git update-index --add --remove --index-info || exit
git update-index --refresh
exit
fi
diff --git a/git-svn.perl b/git-svn.perl
index b28c5bbc72..1da31fdc7c 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -102,7 +102,7 @@ my %cmt_opts = ( 'edit|e' => \$_edit,
);
my %cmd = (
- fetch => [ \&fetch, "Download new revisions from SVN",
+ fetch => [ \&cmd_fetch, "Download new revisions from SVN",
{ 'revision|r=s' => \$_revision, %fc_opts } ],
init => [ \&init, "Initialize a repo for tracking" .
" (requires URL argument)",
@@ -293,6 +293,10 @@ sub init {
setup_git_svn();
}
+sub cmd_fetch {
+ fetch_child_id($GIT_SVN, @_);
+}
+
sub fetch {
check_upgrade_needed();
$SVN_URL ||= file_to_s("$GIT_SVN_DIR/info/url");
@@ -532,7 +536,7 @@ sub show_ignore {
my $repo;
$SVN ||= libsvn_connect($SVN_URL);
my $r = defined $_revision ? $_revision : $SVN->get_latest_revnum;
- libsvn_traverse_ignore(\*STDOUT, $SVN->{svn_path}, $r);
+ libsvn_traverse_ignore(\*STDOUT, '', $r);
}
sub graft_branches {
@@ -571,28 +575,25 @@ sub graft_branches {
sub multi_init {
my $url = shift;
- $_trunk ||= 'trunk';
- $_trunk =~ s#/+$##;
- $url =~ s#/+$## if $url;
- if ($_trunk !~ m#^[a-z\+]+://#) {
- $_trunk = '/' . $_trunk if ($_trunk !~ m#^/#);
- unless ($url) {
- print STDERR "E: '$_trunk' is not a complete URL ",
- "and a separate URL is not specified\n";
- exit 1;
- }
- $_trunk = $url . $_trunk;
+ unless (defined $_trunk || defined $_branches || defined $_tags) {
+ usage(1);
}
- my $ch_id;
- if ($GIT_SVN eq 'git-svn') {
- $ch_id = 1;
- $GIT_SVN = $ENV{GIT_SVN_ID} = 'trunk';
- }
- init_vars();
- unless (-d $GIT_SVN_DIR) {
- print "GIT_SVN_ID set to 'trunk' for $_trunk\n" if $ch_id;
- init($_trunk);
- command_noisy('repo-config', 'svn.trunk', $_trunk);
+ if (defined $_trunk) {
+ my $trunk_url = complete_svn_url($url, $_trunk);
+ my $ch_id;
+ if ($GIT_SVN eq 'git-svn') {
+ $ch_id = 1;
+ $GIT_SVN = $ENV{GIT_SVN_ID} = 'trunk';
+ }
+ init_vars();
+ unless (-d $GIT_SVN_DIR) {
+ if ($ch_id) {
+ print "GIT_SVN_ID set to 'trunk' for ",
+ "$trunk_url ($_trunk)\n";
+ }
+ init($trunk_url);
+ command_noisy('repo-config', 'svn.trunk', $trunk_url);
+ }
}
complete_url_ls_init($url, $_branches, '--branches/-b', '');
complete_url_ls_init($url, $_tags, '--tags/-t', 'tags/');
@@ -839,7 +840,6 @@ sub fetch_child_id {
my $ref = "$GIT_DIR/refs/remotes/$id";
defined(my $pid = open my $fh, '-|') or croak $!;
if (!$pid) {
- $_repack = undef;
$GIT_SVN = $ENV{GIT_SVN_ID} = $id;
init_vars();
fetch(@_);
@@ -847,7 +847,7 @@ sub fetch_child_id {
}
while (<$fh>) {
print $_;
- check_repack() if (/^r\d+ = $sha1/);
+ check_repack() if (/^r\d+ = $sha1/o);
}
close $fh or croak $?;
}
@@ -872,29 +872,34 @@ sub rec_fetch {
}
}
+sub complete_svn_url {
+ my ($url, $path) = @_;
+ $path =~ s#/+$##;
+ $url =~ s#/+$## if $url;
+ if ($path !~ m#^[a-z\+]+://#) {
+ $path = '/' . $path if ($path !~ m#^/#);
+ if (!defined $url || $url !~ m#^[a-z\+]+://#) {
+ fatal("E: '$path' is not a complete URL ",
+ "and a separate URL is not specified\n");
+ }
+ $path = $url . $path;
+ }
+ return $path;
+}
+
sub complete_url_ls_init {
- my ($url, $var, $switch, $pfx) = @_;
- unless ($var) {
+ my ($url, $path, $switch, $pfx) = @_;
+ unless ($path) {
print STDERR "W: $switch not specified\n";
return;
}
- $var =~ s#/+$##;
- if ($var !~ m#^[a-z\+]+://#) {
- $var = '/' . $var if ($var !~ m#^/#);
- unless ($url) {
- print STDERR "E: '$var' is not a complete URL ",
- "and a separate URL is not specified\n";
- exit 1;
- }
- $var = $url . $var;
- }
- my @ls = libsvn_ls_fullurl($var);
- my $old = $GIT_SVN;
+ my $full_url = complete_svn_url($url, $path);
+ my @ls = libsvn_ls_fullurl($full_url);
defined(my $pid = fork) or croak $!;
if (!$pid) {
- foreach my $u (map { "$var/$_" } (grep m!/$!, @ls)) {
+ foreach my $u (map { "$full_url/$_" } (grep m!/$!, @ls)) {
$u =~ s#/+$##;
- if ($u !~ m!\Q$var\E/(.+)$!) {
+ if ($u !~ m!\Q$full_url\E/(.+)$!) {
print STDERR "W: Unrecognized URL: $u\n";
die "This should never happen\n";
}
@@ -912,7 +917,7 @@ sub complete_url_ls_init {
waitpid $pid, 0;
croak $? if $?;
my ($n) = ($switch =~ /^--(\w+)/);
- command_noisy('repo-config', "svn.$n", $var);
+ command_noisy('repo-config', "svn.$n", $full_url);
}
sub common_prefix {
@@ -1405,7 +1410,6 @@ sub git_commit {
# this output is read via pipe, do not change:
print "r$log_msg->{revision} = $commit\n";
- check_repack();
return $commit;
}
diff --git a/git-svnimport.perl b/git-svnimport.perl
index cbaa8ab37c..afbbe63c62 100755
--- a/git-svnimport.perl
+++ b/git-svnimport.perl
@@ -31,12 +31,13 @@ $SIG{'PIPE'}="IGNORE";
$ENV{'TZ'}="UTC";
our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,
- $opt_b,$opt_r,$opt_I,$opt_A,$opt_s,$opt_l,$opt_d,$opt_D,$opt_S,$opt_F,$opt_P);
+ $opt_b,$opt_r,$opt_I,$opt_A,$opt_s,$opt_l,$opt_d,$opt_D,$opt_S,$opt_F,
+ $opt_P,$opt_R);
sub usage() {
print STDERR <<END;
Usage: ${\basename $0} # fetch/update GIT from SVN
- [-o branch-for-HEAD] [-h] [-v] [-l max_rev]
+ [-o branch-for-HEAD] [-h] [-v] [-l max_rev] [-R repack_each_revs]
[-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
[-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg]
[-m] [-M regex] [-A author_file] [-S] [-F] [-P project_name] [SVN_URL]
@@ -44,7 +45,7 @@ END
exit(1);
}
-getopts("A:b:C:dDFhiI:l:mM:o:rs:t:T:SP:uv") or usage();
+getopts("A:b:C:dDFhiI:l:mM:o:rs:t:T:SP:R:uv") or usage();
usage if $opt_h;
my $tag_name = $opt_t || "tags";
@@ -52,6 +53,7 @@ my $trunk_name = $opt_T || "trunk";
my $branch_name = $opt_b || "branches";
my $project_name = $opt_P || "";
$project_name = "/" . $project_name if ($project_name);
+my $repack_after = $opt_R || 1000;
@ARGV == 1 or @ARGV == 2 or usage();
@@ -146,6 +148,7 @@ sub file {
print "... $rev $path ...\n" if $opt_v;
my (undef, $properties);
my $pool = SVN::Pool->new();
+ $path =~ s#^/*##;
eval { (undef, $properties)
= $self->{'svn'}->get_file($path,$rev,$fh,$pool); };
$pool->clear;
@@ -181,6 +184,7 @@ sub ignore {
my($self,$path,$rev) = @_;
print "... $rev $path ...\n" if $opt_v;
+ $path =~ s#^/*##;
my (undef,undef,$properties)
= $self->{'svn'}->get_dir($path,$rev,undef);
if (exists $properties->{'svn:ignore'}) {
@@ -197,6 +201,7 @@ sub ignore {
sub dir_list {
my($self,$path,$rev) = @_;
+ $path =~ s#^/*##;
my ($dirents,undef,$properties)
= $self->{'svn'}->get_dir($path,$rev,undef);
return $dirents;
@@ -354,6 +359,7 @@ open BRANCHES,">>", "$git_dir/svn2git";
sub node_kind($$) {
my ($svnpath, $revision) = @_;
my $pool=SVN::Pool->new;
+ $svnpath =~ s#^/*##;
my $kind = $svn->{'svn'}->check_path($svnpath,$revision,$pool);
$pool->clear;
return $kind;
@@ -934,11 +940,27 @@ if ($opt_l < $current_rev) {
exit;
}
-print "Fetching from $current_rev to $opt_l ...\n" if $opt_v;
+print "Processing from $current_rev to $opt_l ...\n" if $opt_v;
-my $pool=SVN::Pool->new;
-$svn->{'svn'}->get_log("/",$current_rev,$opt_l,0,1,1,\&commit_all,$pool);
-$pool->clear;
+my $from_rev;
+my $to_rev = $current_rev;
+
+while ($to_rev < $opt_l) {
+ $from_rev = $to_rev;
+ $to_rev = $from_rev + $repack_after;
+ $to_rev = $opt_l if $opt_l < $to_rev;
+ print "Fetching from $from_rev to $to_rev ...\n" if $opt_v;
+ my $pool=SVN::Pool->new;
+ $svn->{'svn'}->get_log("/",$from_rev,$to_rev,0,1,1,\&commit_all,$pool);
+ $pool->clear;
+ my $pid = fork();
+ die "Fork: $!\n" unless defined $pid;
+ unless($pid) {
+ exec("git-repack", "-d")
+ or die "Cannot repack: $!\n";
+ }
+ waitpid($pid, 0);
+}
unlink($git_index);
diff --git a/git-tag.sh b/git-tag.sh
index e1bfa82f1e..ecb9100e4b 100755
--- a/git-tag.sh
+++ b/git-tag.sh
@@ -1,7 +1,7 @@
#!/bin/sh
# Copyright (c) 2005 Linus Torvalds
-USAGE='-l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d] [-m <msg>] <tagname> [<head>]'
+USAGE='-l [<pattern>] | [-a | -s | -u <key-id>] [-f | -d | -v] [-m <msg>] <tagname> [<head>]'
SUBDIRECTORY_OK='Yes'
. git-sh-setup
@@ -12,6 +12,7 @@ force=
message=
username=
list=
+verify=
while case "$#" in 0) break ;; esac
do
case "$1" in
@@ -69,6 +70,14 @@ do
echo "Deleted tag $tag_name."
exit $?
;;
+ -v)
+ shift
+ tag_name="$1"
+ tag=$(git-show-ref --verify --hash -- "refs/tags/$tag_name") ||
+ die "Seriously, what tag are you talking about?"
+ git-verify-tag -v "$tag"
+ exit $?
+ ;;
-*)
usage
;;
diff --git a/git-verify-tag.sh b/git-verify-tag.sh
index 36f171b302..8db7dd0b7d 100755
--- a/git-verify-tag.sh
+++ b/git-verify-tag.sh
@@ -34,7 +34,10 @@ t)
;;
esac
+trap 'rm -f "$GIT_DIR/.tmp-vtag"' 0
+
git-cat-file tag "$1" >"$GIT_DIR/.tmp-vtag" || exit 1
+
cat "$GIT_DIR/.tmp-vtag" |
sed '/-----BEGIN PGP/Q' |
gpg --verify "$GIT_DIR/.tmp-vtag" - || exit 1
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index d845e91e20..f46a42296d 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -2274,7 +2274,7 @@ sub git_difftree_body {
my $mode_chnge = "";
if ($diff{'from_mode'} != $diff{'to_mode'}) {
$mode_chnge = "<span class=\"file_status mode_chnge\">[changed";
- if ($from_file_type != $to_file_type) {
+ if ($from_file_type ne $to_file_type) {
$mode_chnge .= " from $from_file_type to $to_file_type";
}
if (($from_mode_oct & 0777) != ($to_mode_oct & 0777)) {
@@ -2378,7 +2378,6 @@ sub git_patchset_body {
my $patch_line;
my $diffinfo;
my (%from, %to);
- my ($from_id, $to_id);
print "<div class=\"patchset\">\n";
@@ -2392,6 +2391,7 @@ sub git_patchset_body {
PATCH:
while ($patch_line) {
my @diff_header;
+ my ($from_id, $to_id);
# git diff header
#assert($patch_line =~ m/^diff /) if DEBUG;
@@ -2403,7 +2403,7 @@ sub git_patchset_body {
while ($patch_line = <$fd>) {
chomp $patch_line;
- last EXTENDED_HEADER if ($patch_line =~ m/^--- /);
+ last EXTENDED_HEADER if ($patch_line =~ m/^--- |^diff /);
if ($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/) {
$from_id = $1;
@@ -2439,11 +2439,15 @@ sub git_patchset_body {
$from{'href'} = href(action=>"blob", hash_base=>$hash_parent,
hash=>$diffinfo->{'from_id'},
file_name=>$from{'file'});
+ } else {
+ delete $from{'href'};
}
if ($diffinfo->{'status'} ne "D") { # not deleted file
$to{'href'} = href(action=>"blob", hash_base=>$hash,
hash=>$diffinfo->{'to_id'},
file_name=>$to{'file'});
+ } else {
+ delete $to{'href'};
}
# this is first patch for raw difftree line with $patch_idx index
# we index @$difftree array from 0, but number patches from 1
@@ -2475,11 +2479,11 @@ sub git_patchset_body {
# match <path>
if ($patch_line =~ s!^((copy|rename) from ).*$!$1! && $from{'href'}) {
$patch_line .= $cgi->a({-href=>$from{'href'}, -class=>"path"},
- esc_path($from{'file'}));
+ esc_path($from{'file'}));
}
if ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {
- $patch_line = $cgi->a({-href=>$to{'href'}, -class=>"path"},
- esc_path($to{'file'}));
+ $patch_line .= $cgi->a({-href=>$to{'href'}, -class=>"path"},
+ esc_path($to{'file'}));
}
# match <mode>
if ($patch_line =~ m/\s(\d{6})$/) {
@@ -2518,8 +2522,10 @@ sub git_patchset_body {
# from-file/to-file diff header
$patch_line = $last_patch_line;
+ last PATCH unless $patch_line;
+ next PATCH if ($patch_line =~ m/^diff /);
#assert($patch_line =~ m/^---/) if DEBUG;
- if ($from{'href'}) {
+ if ($from{'href'} && $patch_line =~ m!^--- "?a/!) {
$patch_line = '--- a/' .
$cgi->a({-href=>$from{'href'}, -class=>"path"},
esc_path($from{'file'}));
@@ -2531,7 +2537,7 @@ sub git_patchset_body {
chomp $patch_line;
#assert($patch_line =~ m/^+++/) if DEBUG;
- if ($to{'href'}) {
+ if ($to{'href'} && $patch_line =~ m!^\+\+\+ "?b/!) {
$patch_line = '+++ b/' .
$cgi->a({-href=>$to{'href'}, -class=>"path"},
esc_path($to{'file'}));
@@ -2813,8 +2819,12 @@ sub git_tags_body {
print "<tr class=\"light\">\n";
}
$alternate ^= 1;
- print "<td><i>$tag{'age'}</i></td>\n" .
- "<td>" .
+ if (defined $tag{'age'}) {
+ print "<td><i>$tag{'age'}</i></td>\n";
+ } else {
+ print "<td></td>\n";
+ }
+ print "<td>" .
$cgi->a({-href => href(action=>$tag{'reftype'}, hash=>$tag{'refid'}),
-class => "list name"}, esc_html($tag{'name'})) .
"</td>\n" .
@@ -2995,7 +3005,7 @@ sub git_project_index {
foreach my $pr (@projects) {
if (!exists $pr->{'owner'}) {
- $pr->{'owner'} = get_file_owner("$projectroot/$project");
+ $pr->{'owner'} = get_file_owner("$projectroot/$pr->{'path'}");
}
my ($path, $owner) = ($pr->{'path'}, $pr->{'owner'});
@@ -3208,9 +3218,14 @@ HTML
esc_html($rev));
print "</td>\n";
}
+ open (my $dd, "-|", git_cmd(), "rev-parse", "$full_rev^")
+ or die_error("could not open git-rev-parse");
+ my $parent_commit = <$dd>;
+ close $dd;
+ chomp($parent_commit);
my $blamed = href(action => 'blame',
file_name => $meta->{'filename'},
- hash_base => $full_rev);
+ hash_base => $parent_commit);
print "<td class=\"linenr\">";
print $cgi->a({ -href => "$blamed#l$orig_lineno",
-id => "l$lineno",
@@ -4423,7 +4438,7 @@ sub git_shortlog {
}
my $refs = git_get_references();
- my @commitlist = parse_commits($head, 101, (100 * $page));
+ my @commitlist = parse_commits($hash, 101, (100 * $page));
my $paging_nav = format_paging_nav('shortlog', $hash, $head, $page, (100 * ($page+1)));
my $next_link = '';
diff --git a/lockfile.c b/lockfile.c
index 261baff049..4824f4dc02 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -27,9 +27,12 @@ static int lock_file(struct lock_file *lk, const char *path)
sprintf(lk->filename, "%s.lock", path);
fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
if (0 <= fd) {
- if (!lk->next) {
+ if (!lk->on_list) {
lk->next = lock_file_list;
lock_file_list = lk;
+ lk->on_list = 1;
+ }
+ if (lock_file_list) {
signal(SIGINT, remove_lock_file_on_signal);
atexit(remove_lock_file);
}
@@ -37,6 +40,8 @@ static int lock_file(struct lock_file *lk, const char *path)
return error("cannot fix permission bits on %s",
lk->filename);
}
+ else
+ lk->filename[0] = 0;
return fd;
}
@@ -44,7 +49,7 @@ int hold_lock_file_for_update(struct lock_file *lk, const char *path, int die_on
{
int fd = lock_file(lk, path);
if (fd < 0 && die_on_error)
- die("unable to create '%s': %s", path, strerror(errno));
+ die("unable to create '%s.lock': %s", path, strerror(errno));
return fd;
}
diff --git a/pack-check.c b/pack-check.c
index c0caaee093..8e123b71ed 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -1,16 +1,18 @@
#include "cache.h"
#include "pack.h"
+#define BATCH (1u<<20)
+
static int verify_packfile(struct packed_git *p)
{
unsigned long index_size = p->index_size;
void *index_base = p->index_base;
SHA_CTX ctx;
unsigned char sha1[20];
- unsigned long pack_size = p->pack_size;
- void *pack_base;
struct pack_header *hdr;
int nr_objects, err, i;
+ unsigned char *packdata;
+ unsigned long datasize;
/* Header consistency check */
hdr = p->pack_base;
@@ -25,11 +27,19 @@ static int verify_packfile(struct packed_git *p)
"while idx size expects %d", nr_objects,
num_packed_objects(p));
+ /* Check integrity of pack data with its SHA-1 checksum */
SHA1_Init(&ctx);
- pack_base = p->pack_base;
- SHA1_Update(&ctx, pack_base, pack_size - 20);
+ packdata = p->pack_base;
+ datasize = p->pack_size - 20;
+ while (datasize) {
+ unsigned long batch = (datasize < BATCH) ? datasize : BATCH;
+ SHA1_Update(&ctx, packdata, batch);
+ datasize -= batch;
+ packdata += batch;
+ }
SHA1_Final(sha1, &ctx);
- if (hashcmp(sha1, (unsigned char *)pack_base + pack_size - 20))
+
+ if (hashcmp(sha1, (unsigned char *)(p->pack_base) + p->pack_size - 20))
return error("Packfile %s SHA1 mismatch with itself",
p->pack_name);
if (hashcmp(sha1, (unsigned char *)index_base + index_size - 40))
diff --git a/refs.c b/refs.c
index e88ed8b2d3..f76b4fe20d 100644
--- a/refs.c
+++ b/refs.c
@@ -726,7 +726,6 @@ static int repack_without_ref(const char *refname)
}
if (!found)
return 0;
- memset(&packlock, 0, sizeof(packlock));
fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
if (fd < 0)
return error("cannot delete '%s' from packed refs", refname);
diff --git a/t/test-lib.sh b/t/test-lib.sh
index bf108d4226..72ea2b2598 100755
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -99,12 +99,12 @@ trap 'echo >&5 "FATAL: Unexpected exit with code $?"; exit 1' exit
test_tick () {
if test -z "${test_tick+set}"
then
- test_tick=432630000
+ test_tick=1112911993
else
test_tick=$(($test_tick + 60))
fi
- GIT_COMMITTER_DATE=$test_tick
- GIT_AUTHOR_DATE=$test_tick
+ GIT_COMMITTER_DATE="$test_tick -0700"
+ GIT_AUTHOR_DATE="$test_tick -0700"
export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
}
diff --git a/tree-walk.c b/tree-walk.c
index 14cc5aea6c..22f4550b6c 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -113,7 +113,6 @@ void traverse_trees(int n, struct tree_desc *t, const char *base, traverse_callb
struct name_entry *entry = xmalloc(n*sizeof(*entry));
for (;;) {
- struct name_entry entry[3];
unsigned long mask = 0;
int i, last;