summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RelNotes-1.6.0.3.txt85
-rw-r--r--Documentation/config.txt13
-rw-r--r--Documentation/git-check-attr.txt50
-rw-r--r--Documentation/git-log.txt9
-rw-r--r--Documentation/git-push.txt24
-rw-r--r--Documentation/git-rev-list.txt6
-rw-r--r--Documentation/git-svn.txt8
-rw-r--r--Documentation/gitattributes.txt4
-rw-r--r--Documentation/githooks.txt13
-rw-r--r--Makefile2
-rw-r--r--builtin-apply.c22
-rw-r--r--builtin-blame.c2
-rw-r--r--builtin-checkout.c2
-rw-r--r--builtin-commit.c2
-rw-r--r--builtin-for-each-ref.c4
-rw-r--r--builtin-init-db.c12
-rw-r--r--builtin-merge-recursive.c23
-rw-r--r--builtin-merge.c6
-rw-r--r--builtin-pack-objects.c2
-rw-r--r--builtin-prune.c22
-rw-r--r--builtin-push.c2
-rw-r--r--builtin-remote.c41
-rw-r--r--builtin-reset.c3
-rw-r--r--builtin-rm.c23
-rwxr-xr-xcontrib/completion/git-completion.bash36
-rwxr-xr-xcontrib/examples/git-remote.perl2
-rw-r--r--contrib/hooks/setgitperms.perl4
-rwxr-xr-xcontrib/stats/packinfo.pl14
-rw-r--r--csum-file.c18
-rw-r--r--csum-file.h1
-rw-r--r--diff.c102
-rw-r--r--dir.c20
-rw-r--r--dir.h3
-rw-r--r--fast-import.c4
-rwxr-xr-xgit-rebase--interactive.sh31
-rwxr-xr-xgit-rebase.sh18
-rwxr-xr-xgit-stash.sh11
-rwxr-xr-xgit-submodule.sh9
-rwxr-xr-xgit-svn.perl2
-rw-r--r--git.c2
-rwxr-xr-xgitweb/gitweb.perl10
-rw-r--r--index-pack.c8
-rw-r--r--pack-write.c2
-rw-r--r--remote.c9
-rw-r--r--setup.c9
-rw-r--r--sha1_file.c6
-rwxr-xr-xt/t0001-init.sh32
-rwxr-xr-x[-rw-r--r--]t/t0024-crlf-archive.sh0
-rwxr-xr-xt/t1300-repo-config.sh10
-rwxr-xr-xt/t1301-shared-repo.sh3
-rwxr-xr-xt/t3030-merge-recursive.sh11
-rwxr-xr-xt/t3404-rebase-interactive.sh11
-rwxr-xr-xt/t3409-rebase-hook.sh126
-rwxr-xr-xt/t3600-rm.sh25
-rwxr-xr-xt/t4012-diff-binary.sh21
-rwxr-xr-xt/t4018-diff-funcname.sh22
-rwxr-xr-xt/t4128-apply-root.sh52
-rwxr-xr-xt/t7600-merge.sh26
-rwxr-xr-xt/t9500-gitweb-standalone-no-errors.sh49
-rw-r--r--t/test-lib.sh3
-rw-r--r--transport.c4
-rw-r--r--xdiff-interface.c16
-rw-r--r--xdiff-interface.h2
63 files changed, 855 insertions, 259 deletions
diff --git a/Documentation/RelNotes-1.6.0.3.txt b/Documentation/RelNotes-1.6.0.3.txt
index ea1420d77a..214a400aa2 100644
--- a/Documentation/RelNotes-1.6.0.3.txt
+++ b/Documentation/RelNotes-1.6.0.3.txt
@@ -13,17 +13,100 @@ Fixes since v1.6.0.2
* Continuing "git rebase -i" was also very confused when the user left
some staged changes in the index after "edit".
+* "git rebase -i" now honors the pre-rebase hook, just like the
+ other rebase implementations "git rebase" and "git rebase -m".
+
+* "git rebase -i" incorrectly aborted when there is no commit to replay.
+
* Behaviour of "git diff --quiet" was inconsistent with "diff --exit-code"
with the output redirected to /dev/null.
+* "git diff --no-index" on binary files no longer outputs a bogus
+ "diff --git" header line.
+
+* Hunk headers in "git diff" default to using extended regular
+ expressions, fixing some of the internal patterns on non-GNU
+ platforms.
+
+* New config "diff.*.xfuncname" exposes extended regular expressions
+ for user specified hunk header patterns.
+
+* "git index-pack" was recently broken and mishandled objects added by
+ thin-pack completion processing under memory pressure.
+
+* "git stash apply sash@{1}" was fixed to error out. Prior versions
+ would have applied stash@{0} incorrectly.
+
+* "git stash apply" now offers a better suggestion on how to continue
+ if the working tree is currently dirty.
+
+* "git for-each-ref --format=%(subject)" fixed for commits with no
+ no newline in the message body.
+
+* "git remote" fixed to protect printf from user input.
+
+* "git remote show -v" now displays all URLs of a remote.
+
+* "git checkout -q" once again suppresses the locally modified file list.
+
+* "git clone -q", "git fetch -q" asks remote side to not send
+ progress messages, actually making their output quiet.
+
+* Cross-directory renames are no longer used when creating packs. This
+ allows more graceful behavior on filesystems like sshfs.
+
+* Stale temporary files under $GIT_DIR/objects/pack are now cleaned up
+ automatically by "git prune".
+
+* "git merge" once again removes directories after the last file has
+ been removed from it during the merge.
+
+* "git merge" did not allocate enough memory for the structure itself when
+ enumerating the parents of the resulting commit.
+
+* "git blame -C -C" no longer segfaults while trying to pass blame if
+ it encounters a submodule reference.
+
+* "git rm" incorrectly claimed that you have local modifications when a
+ path was merely stat-dirty.
+
+* "git svn" fixed to display an error message when 'set-tree' failed,
+ instead of a Perl compile error.
+
+* "git submodule" fixed to handle checking out a different commit
+ than HEAD after initializing the submodule.
+
+* The "git commit" error message when there are still unmerged
+ files present was clarified to match "git write-tree".
+
+* "git init" was confused when core.bare or core.sharedRepository are set
+ in system or user global configuration file by mistake. When --bare or
+ --shared is given from the command line, these now override such
+ settings made outside the repositories.
+
+* Some segfaults due to uncaught NULL pointers were fixed in multiple
+ tools such as apply, reset, update-index.
+
+* Solaris builds now default to OLD_ICONV=1 to avoid compile warnings;
+ Solaris 8 does not define NEEDS_LIBICONV by default.
+
* "Git.pm" tests relied on unnecessarily more recent version of Perl.
* "gitweb" triggered undef warning on commits without log messages.
+* "gitweb" triggered undef warnings on missing trees.
+
+* "gitweb" now removes PATH_INFO from its URLs so users don't have
+ to manually set the URL in the gitweb configuration.
+
+* Bash completion removed support for legacy "git-fetch", "git-push"
+ and "git-pull" as these are no longer installed. Dashless form
+ ("git fetch") is still however supported.
+
Many other documentation updates.
--
exec >/var/tmp/1
-O=v1.6.0.2-32-g8d11fde
+O=v1.6.0.2-95-g72d404d
echo O=$(git describe maint)
git shortlog --no-merges $O..maint
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3727239891..87b028fbc1 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -363,8 +363,17 @@ core.pager::
variable. Note that git sets the `LESS` environment
variable to `FRSX` if it is unset when it runs the
pager. One can change these settings by setting the
- `LESS` variable to some other value or by giving the
- `core.pager` option a value such as "`less -+FRSX`".
+ `LESS` variable to some other value. Alternately,
+ these settings can be overridden on a project or
+ global basis by setting the `core.pager` option.
+ Setting `core.pager` has no affect on the `LESS`
+ environment variable behaviour above, so if you want
+ to override git's default settings this way, you need
+ to be explicit. For example, to disable the S option
+ in a backward compatible manner, set `core.pager`
+ to "`less -+$LESS -FRX`". This will be passed to the
+ shell by git, which will translate the final command to
+ "`LESS=FRSX less -+FRSX -FRX`".
core.whitespace::
A comma separated list of common whitespace problems to
diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt
index 2b821f2a1d..4b3c2b0b06 100644
--- a/Documentation/git-check-attr.txt
+++ b/Documentation/git-check-attr.txt
@@ -22,6 +22,56 @@ OPTIONS
arguments as path names. If not supplied, only the first argument will
be treated as an attribute.
+OUTPUT
+------
+
+The output is of the form:
+<path> COLON SP <attribute> COLON SP <info> LF
+
+Where <path> is the path of a file being queried, <attribute> is an attribute
+being queried and <info> can be either:
+
+'unspecified';; when the attribute is not defined for the path.
+'unset';; when the attribute is defined to false.
+'set';; when the attribute is defined to true.
+<value>;; when a value has been assigned to the attribute.
+
+EXAMPLES
+--------
+
+In the examples, the following '.gitattributes' file is used:
+---------------
+*.java diff=java -crlf myAttr
+NoMyAttr.java !myAttr
+README caveat=unspecified
+---------------
+
+* Listing a single attribute:
+---------------
+$ git check-attr diff org/example/MyClass.java
+org/example/MyClass.java: diff: java
+---------------
+
+* Listing multiple attributes for a file:
+---------------
+$ git check-attr crlf diff myAttr -- org/example/MyClass.java
+org/example/MyClass.java: crlf: unset
+org/example/MyClass.java: diff: java
+org/example/MyClass.java: myAttr: set
+---------------
+
+* Listing attribute for multiple files:
+---------------
+$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
+org/example/MyClass.java: myAttr: set
+org/example/NoMyAttr.java: myAttr: unspecified
+---------------
+
+* Not all values are equally unambiguous:
+---------------
+$ git check-attr caveat README
+README: caveat: unspecified
+---------------
SEE ALSO
--------
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 0446bad7e5..93a2a227c4 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -8,7 +8,7 @@ git-log - Show commit logs
SYNOPSIS
--------
-'git log' <option>...
+'git log' [<options>] [<since>..<until>] [[\--] <path>...]
DESCRIPTION
-----------
@@ -57,8 +57,11 @@ include::diff-options.txt[]
Note that only message is considered, if also a diff is shown
its size is not included.
-<path>...::
- Show only commits that affect any of the specified paths.
+[\--] <path>...::
+ Show only commits that affect any of the specified paths. To
+ prevent confusion with options and branch names, paths may need
+ to be prefixed with "\-- " to separate them from options or
+ refnames.
include::rev-list-options.txt[]
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 45c96435fa..6150b1b959 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,8 +9,8 @@ git-push - Update remote refs along with associated objects
SYNOPSIS
--------
[verse]
-'git push' [--all] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
- [--repo=all] [-f | --force] [-v | --verbose]
+'git push' [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>]
+ [--repo=<repository>] [-f | --force] [-v | --verbose]
[<repository> <refspec>...]
DESCRIPTION
@@ -101,9 +101,23 @@ nor in any Push line of the corresponding remotes file---see below).
This flag disables the check. This can cause the
remote repository to lose commits; use it with care.
---repo=<repo>::
- When no repository is specified the command defaults to
- "origin"; this overrides it.
+--repo=<repository>::
+ This option is only relevant if no <repository> argument is
+ passed in the invocation. In this case, 'git-push' derives the
+ remote name from the current branch: If it tracks a remote
+ branch, then that remote repository is pushed to. Otherwise,
+ the name "origin" is used. For this latter case, this option
+ can be used to override the name "origin". In other words,
+ the difference between these two commands
++
+--------------------------
+git push public #1
+git push --repo=public #2
+--------------------------
++
+is that #1 always pushes to "public" whereas #2 pushes to "public"
+only if the current branch does not track a remote branch. This is
+useful if you write an alias or script around 'git-push'.
--thin::
--no-thin::
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index fd1de92e34..1c9cc28895 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -32,9 +32,9 @@ SYNOPSIS
[ \--cherry-pick ]
[ \--encoding[=<encoding>] ]
[ \--(author|committer|grep)=<pattern> ]
- [ \--regexp-ignore-case | \-i ]
- [ \--extended-regexp | \-E ]
- [ \--fixed-strings | \-F ]
+ [ \--regexp-ignore-case | -i ]
+ [ \--extended-regexp | -E ]
+ [ \--fixed-strings | -F ]
[ \--date={local|relative|default|iso|rfc|short} ]
[ [\--objects | \--objects-edge] [ \--unpacked ] ]
[ \--pretty | \--header ]
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 1e644ca6dc..82d03b4ced 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -473,7 +473,7 @@ Tracking and contributing to the trunk of a Subversion-managed project:
------------------------------------------------------------------------
# Clone a repo (like git clone):
- git svn clone http://svn.foo.org/project/trunk
+ git svn clone http://svn.example.com/project/trunk
# Enter the newly cloned directory:
cd trunk
# You should be on master branch, double-check with git-branch
@@ -495,7 +495,7 @@ Tracking and contributing to an entire Subversion-managed project
------------------------------------------------------------------------
# Clone a repo (like git clone):
- git svn clone http://svn.foo.org/project -T trunk -b branches -t tags
+ git svn clone http://svn.example.com/project -T trunk -b branches -t tags
# View all branches and tags you have cloned:
git branch -r
# Reset your master to trunk (or any other branch, replacing 'trunk'
@@ -514,7 +514,7 @@ have each person clone that repository with 'git-clone':
------------------------------------------------------------------------
# Do the initial import on a server
- ssh server "cd /pub && git svn clone http://svn.foo.org/project
+ ssh server "cd /pub && git svn clone http://svn.example.com/project
# Clone locally - make sure the refs/remotes/ space matches the server
mkdir project
cd project
@@ -523,7 +523,7 @@ have each person clone that repository with 'git-clone':
git config --add remote.origin.fetch '+refs/remotes/*:refs/remotes/*'
git fetch
# Initialize git-svn locally (be sure to use the same URL and -T/-b/-t options as were used on server)
- git svn init http://svn.foo.org/project
+ git svn init http://svn.example.com/project
# Pull the latest changes from Subversion
git svn rebase
------------------------------------------------------------------------
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 89627688b8..53da9b4f6b 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -288,13 +288,13 @@ for paths.
*.tex diff=tex
------------------------
-Then, you would define a "diff.tex.funcname" configuration to
+Then, you would define a "diff.tex.xfuncname" configuration to
specify a regular expression that matches a line that you would
want to appear as the hunk header "TEXT", like this:
------------------------
[diff "tex"]
- funcname = "^\\(\\\\\\(sub\\)*section{.*\\)$"
+ xfuncname = "^(\\\\(sub)*section\\{.*)$"
------------------------
Note. A single level of backslashes are eaten by the
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 046a2a7fe7..5faaaa5fed 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -87,12 +87,12 @@ default log message, and before the editor is started.
It takes one to three parameters. The first is the name of the file
that the commit log message. The second is the source of the commit
-message, and can be: `message` (if a `\-m` or `\-F` option was
-given); `template` (if a `\-t` option was given or the
+message, and can be: `message` (if a `-m` or `-F` option was
+given); `template` (if a `-t` option was given or the
configuration option `commit.template` is set); `merge` (if the
commit is a merge or a `.git/MERGE_MSG` file exists); `squash`
(if a `.git/SQUASH_MSG` file exists); or `commit`, followed by
-a commit SHA1 (if a `\-c`, `\-C` or `\--amend` option was given).
+a commit SHA1 (if a `-c`, `-C` or `\--amend` option was given).
If the exit status is non-zero, 'git-commit' will abort.
@@ -130,6 +130,13 @@ parameter, and is invoked after a commit is made.
This hook is meant primarily for notification, and cannot affect
the outcome of 'git-commit'.
+pre-rebase
+----------
+
+This hook is called by 'git-rebase' and can be used to prevent a branch
+from getting rebased.
+
+
post-checkout
-----------
diff --git a/Makefile b/Makefile
index 8d81095765..0d40f0ecca 100644
--- a/Makefile
+++ b/Makefile
@@ -637,8 +637,8 @@ ifeq ($(uname_S),SunOS)
NO_MEMMEM = YesPlease
NO_HSTRERROR = YesPlease
NO_MKDTEMP = YesPlease
+ OLD_ICONV = UnfortunatelyYes
ifeq ($(uname_R),5.8)
- NEEDS_LIBICONV = YesPlease
NO_UNSETENV = YesPlease
NO_SETENV = YesPlease
NO_C99_FORMAT = YesPlease
diff --git a/builtin-apply.c b/builtin-apply.c
index 20bef1f21d..e9d49f133a 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -13,6 +13,7 @@
#include "delta.h"
#include "builtin.h"
#include "string-list.h"
+#include "dir.h"
/*
* --check turns on checking that the working tree matches the
@@ -809,6 +810,13 @@ static int parse_git_header(char *line, int len, unsigned int size, struct patch
* the default name from the header.
*/
patch->def_name = git_header_name(line, len);
+ if (patch->def_name && root) {
+ char *s = xmalloc(root_len + strlen(patch->def_name) + 1);
+ strcpy(s, root);
+ strcpy(s + root_len, patch->def_name);
+ free(patch->def_name);
+ patch->def_name = s;
+ }
line += len;
size -= len;
@@ -1696,7 +1704,7 @@ static int match_fragment(struct image *img,
fixlen = ws_fix_copy(buf, orig, oldlen, ws_rule, NULL);
/* Try fixing the line in the target */
- if (sizeof(tgtfixbuf) < tgtlen)
+ if (sizeof(tgtfixbuf) > tgtlen)
tgtfix = tgtfixbuf;
else
tgtfix = xmalloc(tgtlen);
@@ -2585,6 +2593,8 @@ static void build_fake_ancestor(struct patch *list, const char *filename)
sha1_ptr = sha1;
ce = make_cache_entry(patch->old_mode, sha1_ptr, name, 0, 0);
+ if (!ce)
+ die("make_cache_entry failed for path '%s'", name);
if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD))
die ("Could not add %s to temporary index", name);
}
@@ -2735,15 +2745,7 @@ static void remove_file(struct patch *patch, int rmdir_empty)
warning("unable to remove submodule %s",
patch->old_name);
} else if (!unlink(patch->old_name) && rmdir_empty) {
- char *name = xstrdup(patch->old_name);
- char *end = strrchr(name, '/');
- while (end) {
- *end = 0;
- if (rmdir(name))
- break;
- end = strrchr(name, '/');
- }
- free(name);
+ remove_path(patch->old_name);
}
}
}
diff --git a/builtin-blame.c b/builtin-blame.c
index 9bc901c292..101c4162da 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -1136,6 +1136,8 @@ static int find_copy_in_parent(struct scoreboard *sb,
if (!DIFF_FILE_VALID(p->one))
continue; /* does not exist in parent */
+ if (S_ISGITLINK(p->one->mode))
+ continue; /* ignore git links */
if (porigin && !strcmp(p->one->path, porigin->path))
/* find_move already dealt with this path */
continue;
diff --git a/builtin-checkout.c b/builtin-checkout.c
index 1ee23468ff..1deda927cd 100644
--- a/builtin-checkout.c
+++ b/builtin-checkout.c
@@ -328,7 +328,7 @@ static int merge_working_tree(struct checkout_opts *opts,
commit_locked_index(lock_file))
die("unable to write new index file");
- if (!opts->force)
+ if (!opts->force && !opts->quiet)
show_local_changes(&new->commit->object);
return 0;
diff --git a/builtin-commit.c b/builtin-commit.c
index c870037b07..e2a7e48b1c 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -639,7 +639,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix)
active_cache_tree = cache_tree();
if (cache_tree_update(active_cache_tree,
active_cache, active_nr, 0, 0) < 0) {
- error("Error building trees");
+ error("Error building trees; the index is unmerged?");
return 0;
}
diff --git a/builtin-for-each-ref.c b/builtin-for-each-ref.c
index 21e92bbcb5..72c087840c 100644
--- a/builtin-for-each-ref.c
+++ b/builtin-for-each-ref.c
@@ -320,9 +320,7 @@ static const char *find_wholine(const char *who, int wholen, const char *buf, un
static const char *copy_line(const char *buf)
{
- const char *eol = strchr(buf, '\n');
- if (!eol)
- return "";
+ const char *eol = strchrnul(buf, '\n');
return xmemdupz(buf, eol - buf);
}
diff --git a/builtin-init-db.c b/builtin-init-db.c
index 8140c1299a..d30c3fe2ca 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -17,6 +17,9 @@
#define TEST_FILEMODE 1
#endif
+static int init_is_bare_repository = 0;
+static int init_shared_repository = -1;
+
static void safe_create_dir(const char *dir, int share)
{
if (mkdir(dir, 0777) < 0) {
@@ -191,6 +194,9 @@ static int create_default_files(const char *template_path)
copy_templates(template_path);
git_config(git_default_config, NULL);
+ is_bare_repository_cfg = init_is_bare_repository;
+ if (init_shared_repository != -1)
+ shared_repository = init_shared_repository;
/*
* We would have created the above under user's umask -- under
@@ -277,6 +283,8 @@ int init_db(const char *template_dir, unsigned int flags)
safe_create_dir(get_git_dir(), 0);
+ init_is_bare_repository = is_bare_repository();
+
/* Check to see if the repository version is right.
* Note that a newly created repository does not have
* config file, so this will not fail. What we are catching
@@ -381,9 +389,9 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir,
sizeof(git_dir)), 0);
} else if (!strcmp(arg, "--shared"))
- shared_repository = PERM_GROUP;
+ init_shared_repository = PERM_GROUP;
else if (!prefixcmp(arg, "--shared="))
- shared_repository = git_config_perm("arg", arg+9);
+ init_shared_repository = git_config_perm("arg", arg+9);
else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
flags |= INIT_DB_QUIET;
else
diff --git a/builtin-merge-recursive.c b/builtin-merge-recursive.c
index 43e55bf901..b9738655ad 100644
--- a/builtin-merge-recursive.c
+++ b/builtin-merge-recursive.c
@@ -18,6 +18,7 @@
#include "ll-merge.h"
#include "interpolate.h"
#include "attr.h"
+#include "dir.h"
#include "merge-recursive.h"
static int subtree_merge;
@@ -416,24 +417,6 @@ static int update_stages(const char *path, struct diff_filespec *o,
return 0;
}
-static int remove_path(const char *name)
-{
- int ret;
- char *slash, *dirs;
-
- ret = unlink(name);
- if (ret)
- return ret;
- dirs = xstrdup(name);
- while ((slash = strrchr(name, '/'))) {
- *slash = '\0';
- if (rmdir(name) != 0)
- break;
- }
- free(dirs);
- return ret;
-}
-
static int remove_file(int clean, const char *path, int no_wd)
{
int update_cache = index_only || clean;
@@ -444,10 +427,8 @@ static int remove_file(int clean, const char *path, int no_wd)
return -1;
}
if (update_working_directory) {
- unlink(path);
- if (errno != ENOENT || errno != EISDIR)
+ if (remove_path(path))
return -1;
- remove_path(path);
}
return 0;
}
diff --git a/builtin-merge.c b/builtin-merge.c
index b280444e10..d0bf1fc1ed 100644
--- a/builtin-merge.c
+++ b/builtin-merge.c
@@ -442,6 +442,8 @@ static int git_merge_config(const char *k, const char *v, void *cb)
buf = xstrdup(v);
argc = split_cmdline(buf, &argv);
+ if (argc < 0)
+ die("Bad branch.%s.mergeoptions string", branch);
argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
argc++;
@@ -649,12 +651,12 @@ static void add_strategies(const char *string, unsigned attr)
static int merge_trivial(void)
{
unsigned char result_tree[20], result_commit[20];
- struct commit_list *parent = xmalloc(sizeof(struct commit_list *));
+ struct commit_list *parent = xmalloc(sizeof(*parent));
write_tree_trivial(result_tree);
printf("Wonderful.\n");
parent->item = lookup_commit(head);
- parent->next = xmalloc(sizeof(struct commit_list *));
+ parent->next = xmalloc(sizeof(*parent->next));
parent->next->item = remoteheads->item;
parent->next->next = NULL;
commit_tree(merge_msg.buf, result_tree, parent, result_commit);
diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c
index 217fd49da9..4004e73e40 100644
--- a/builtin-pack-objects.c
+++ b/builtin-pack-objects.c
@@ -465,7 +465,7 @@ static void write_pack_file(void)
char tmpname[PATH_MAX];
int fd;
snprintf(tmpname, sizeof(tmpname),
- "%s/tmp_pack_XXXXXX", get_object_directory());
+ "%s/pack/tmp_pack_XXXXXX", get_object_directory());
fd = xmkstemp(tmpname);
pack_tmp_name = xstrdup(tmpname);
f = sha1fd(fd, pack_tmp_name);
diff --git a/builtin-prune.c b/builtin-prune.c
index c767a0ac89..1663f8bdb1 100644
--- a/builtin-prune.c
+++ b/builtin-prune.c
@@ -13,7 +13,7 @@ static const char * const prune_usage[] = {
static int show_only;
static unsigned long expire;
-static int prune_tmp_object(char *path, const char *filename)
+static int prune_tmp_object(const char *path, const char *filename)
{
const char *fullpath = mkpath("%s/%s", path, filename);
if (expire) {
@@ -110,24 +110,22 @@ static void prune_object_dir(const char *path)
/*
* Write errors (particularly out of space) can result in
* failed temporary packs (and more rarely indexes and other
- * files begining with "tmp_") accumulating in the
- * object directory.
+ * files begining with "tmp_") accumulating in the object
+ * and the pack directories.
*/
-static void remove_temporary_files(void)
+static void remove_temporary_files(const char *path)
{
DIR *dir;
struct dirent *de;
- char* dirname=get_object_directory();
- dir = opendir(dirname);
+ dir = opendir(path);
if (!dir) {
- fprintf(stderr, "Unable to open object directory %s\n",
- dirname);
+ fprintf(stderr, "Unable to open directory %s\n", path);
return;
}
while ((de = readdir(dir)) != NULL)
if (!prefixcmp(de->d_name, "tmp_"))
- prune_tmp_object(dirname, de->d_name);
+ prune_tmp_object(path, de->d_name);
closedir(dir);
}
@@ -141,6 +139,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
"expire objects older than <time>"),
OPT_END()
};
+ char *s;
save_commit_buffer = 0;
init_revisions(&revs, prefix);
@@ -163,6 +162,9 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
prune_object_dir(get_object_directory());
prune_packed_objects(show_only);
- remove_temporary_files();
+ remove_temporary_files(get_object_directory());
+ s = xstrdup(mkpath("%s/pack", get_object_directory()));
+ remove_temporary_files(s);
+ free(s);
return 0;
}
diff --git a/builtin-push.c b/builtin-push.c
index c1ed68d938..f5cc76266b 100644
--- a/builtin-push.c
+++ b/builtin-push.c
@@ -10,7 +10,7 @@
#include "parse-options.h"
static const char * const push_usage[] = {
- "git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=all] [-f | --force] [-v] [<repository> <refspec>...]",
+ "git push [--all | --mirror] [--dry-run] [--tags] [--receive-pack=<git-receive-pack>] [--repo=<repository>] [-f | --force] [-v] [<repository> <refspec>...]",
NULL,
};
diff --git a/builtin-remote.c b/builtin-remote.c
index 01945a8651..90a4e35828 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -407,14 +407,15 @@ static int rm(int argc, const char **argv)
return i;
}
-static void show_list(const char *title, struct string_list *list)
+static void show_list(const char *title, struct string_list *list,
+ const char *extra_arg)
{
int i;
if (!list->nr)
return;
- printf(title, list->nr > 1 ? "es" : "");
+ printf(title, list->nr > 1 ? "es" : "", extra_arg);
printf("\n ");
for (i = 0; i < list->nr; i++)
printf("%s%s", i ? " " : "", list->items[i].string);
@@ -477,7 +478,6 @@ static int show(int argc, const char **argv)
memset(&states, 0, sizeof(states));
for (; argc; argc--, argv++) {
- struct strbuf buf;
int i;
get_remote_ref_states(*argv, &states, !no_query);
@@ -503,18 +503,16 @@ static int show(int argc, const char **argv)
}
if (!no_query) {
- strbuf_init(&buf, 0);
- strbuf_addf(&buf, " New remote branch%%s (next fetch "
- "will store in remotes/%s)", states.remote->name);
- show_list(buf.buf, &states.new);
- strbuf_release(&buf);
+ show_list(" New remote branch%s (next fetch "
+ "will store in remotes/%s)",
+ &states.new, states.remote->name);
show_list(" Stale tracking branch%s (use 'git remote "
- "prune')", &states.stale);
+ "prune')", &states.stale, "");
}
if (no_query)
for_each_ref(append_ref_to_tracked_list, &states);
- show_list(" Tracked remote branch%s", &states.tracked);
+ show_list(" Tracked remote branch%s", &states.tracked, "");
if (states.remote->push_refspec_nr) {
printf(" Local branch%s pushed with 'git push'\n ",
@@ -652,10 +650,13 @@ static int get_one_entry(struct remote *remote, void *priv)
{
struct string_list *list = priv;
- string_list_append(remote->name, list)->util = remote->url_nr ?
- (void *)remote->url[0] : NULL;
- if (remote->url_nr > 1)
- warning("Remote %s has more than one URL", remote->name);
+ if (remote->url_nr > 0) {
+ int i;
+
+ for (i = 0; i < remote->url_nr; i++)
+ string_list_append(remote->name, list)->util = (void *)remote->url[i];
+ } else
+ string_list_append(remote->name, list)->util = NULL;
return 0;
}
@@ -671,10 +672,14 @@ static int show_all(void)
sort_string_list(&list);
for (i = 0; i < list.nr; i++) {
struct string_list_item *item = list.items + i;
- printf("%s%s%s\n", item->string,
- verbose ? "\t" : "",
- verbose && item->util ?
- (const char *)item->util : "");
+ if (verbose)
+ printf("%s\t%s\n", item->string,
+ item->util ? (const char *)item->util : "");
+ else {
+ if (i && !strcmp((item - 1)->string, item->string))
+ continue;
+ printf("%s\n", item->string);
+ }
}
}
return result;
diff --git a/builtin-reset.c b/builtin-reset.c
index c24c219091..16e6bb20f1 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -121,6 +121,9 @@ static void update_index_from_diff(struct diff_queue_struct *q,
struct cache_entry *ce;
ce = make_cache_entry(one->mode, one->sha1, one->path,
0, 0);
+ if (!ce)
+ die("make_cache_entry failed for path '%s'",
+ one->path);
add_cache_entry(ce, ADD_CACHE_OK_TO_ADD |
ADD_CACHE_OK_TO_REPLACE);
} else
diff --git a/builtin-rm.c b/builtin-rm.c
index fdac34f242..e06640cf8d 100644
--- a/builtin-rm.c
+++ b/builtin-rm.c
@@ -29,26 +29,6 @@ static void add_list(const char *name)
list.name[list.nr++] = name;
}
-static int remove_file(const char *name)
-{
- int ret;
- char *slash;
-
- ret = unlink(name);
- if (ret && errno == ENOENT)
- /* The user has removed it from the filesystem by hand */
- ret = errno = 0;
-
- if (!ret && (slash = strrchr(name, '/'))) {
- char *n = xstrdup(name);
- do {
- n[slash - name] = 0;
- name = n;
- } while (!rmdir(name) && (slash = strrchr(name, '/')));
- }
- return ret;
-}
-
static int check_local_mod(unsigned char *head, int index_only)
{
/* items in list are already sorted in the cache order,
@@ -157,6 +137,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
if (read_cache() < 0)
die("index file corrupt");
+ refresh_cache(REFRESH_QUIET);
pathspec = get_pathspec(prefix, argv);
seen = NULL;
@@ -239,7 +220,7 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
int removed = 0;
for (i = 0; i < list.nr; i++) {
const char *path = list.name[i];
- if (!remove_file(path)) {
+ if (!remove_path(path)) {
removed = 1;
continue;
}
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 3bc45f6b47..751e273e1a 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -799,14 +799,9 @@ _git_fetch ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
- case "${COMP_WORDS[0]},$COMP_CWORD" in
- git-fetch*,1)
+ if [ "$COMP_CWORD" = 2 ]; then
__gitcomp "$(__git_remotes)"
- ;;
- git,2)
- __gitcomp "$(__git_remotes)"
- ;;
- *)
+ else
case "$cur" in
*:*)
local pfx=""
@@ -825,8 +820,7 @@ _git_fetch ()
__gitcomp "$(__git_refs2 "$remote")"
;;
esac
- ;;
- esac
+ fi
}
_git_format_patch ()
@@ -1063,36 +1057,25 @@ _git_pull ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
- case "${COMP_WORDS[0]},$COMP_CWORD" in
- git-pull*,1)
- __gitcomp "$(__git_remotes)"
- ;;
- git,2)
+ if [ "$COMP_CWORD" = 2 ]; then
__gitcomp "$(__git_remotes)"
- ;;
- *)
+ else
local remote
case "${COMP_WORDS[0]}" in
git-pull) remote="${COMP_WORDS[1]}" ;;
git) remote="${COMP_WORDS[2]}" ;;
esac
__gitcomp "$(__git_refs "$remote")"
- ;;
- esac
+ fi
}
_git_push ()
{
local cur="${COMP_WORDS[COMP_CWORD]}"
- case "${COMP_WORDS[0]},$COMP_CWORD" in
- git-push*,1)
- __gitcomp "$(__git_remotes)"
- ;;
- git,2)
+ if [ "$COMP_CWORD" = 2 ]; then
__gitcomp "$(__git_remotes)"
- ;;
- *)
+ else
case "$cur" in
*:*)
local remote
@@ -1116,8 +1099,7 @@ _git_push ()
__gitcomp "$(__git_refs)"
;;
esac
- ;;
- esac
+ fi
}
_git_rebase ()
diff --git a/contrib/examples/git-remote.perl b/contrib/examples/git-remote.perl
index 36bd54c985..b17952a785 100755
--- a/contrib/examples/git-remote.perl
+++ b/contrib/examples/git-remote.perl
@@ -309,7 +309,7 @@ sub update_remote {
}
}
} else {
- print STDERR "Remote group $name does not exists.\n";
+ print STDERR "Remote group $name does not exist.\n";
exit(1);
}
for (@remotes) {
diff --git a/contrib/hooks/setgitperms.perl b/contrib/hooks/setgitperms.perl
index dab7c8e3a1..a577ad095f 100644
--- a/contrib/hooks/setgitperms.perl
+++ b/contrib/hooks/setgitperms.perl
@@ -50,7 +50,7 @@ if ((@ARGV < 0) || !GetOptions(
)) { die $usage; }
die $usage unless ($read_mode xor $write_mode);
-my $topdir = `git-rev-parse --show-cdup` or die "\n"; chomp $topdir;
+my $topdir = `git rev-parse --show-cdup` or die "\n"; chomp $topdir;
my $gitdir = $topdir . '.git';
my $gitmeta = $topdir . '.gitmeta';
@@ -155,7 +155,7 @@ elsif ($read_mode) {
open (OUT, ">$gitmeta.tmp") or die "Could not open $gitmeta.tmp for writing: $!\n";
}
- my @files = `git-ls-files`;
+ my @files = `git ls-files`;
my %dirs;
foreach my $path (@files) {
diff --git a/contrib/stats/packinfo.pl b/contrib/stats/packinfo.pl
index f4a7b62cd9..be188c0f11 100755
--- a/contrib/stats/packinfo.pl
+++ b/contrib/stats/packinfo.pl
@@ -1,9 +1,9 @@
#!/usr/bin/perl
#
# This tool will print vaguely pretty information about a pack. It
-# expects the output of "git-verify-pack -v" as input on stdin.
+# expects the output of "git verify-pack -v" as input on stdin.
#
-# $ git-verify-pack -v | packinfo.pl
+# $ git verify-pack -v | packinfo.pl
#
# This prints some full-pack statistics; currently "all sizes", "all
# path sizes", "tree sizes", "tree path sizes", and "depths".
@@ -20,7 +20,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -tree
+# $ git verify-pack -v | packinfo.pl -tree
#
# the trees of objects are output along with the stats. This looks
# like:
@@ -43,7 +43,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -tree -filenames
+# $ git verify-pack -v | packinfo.pl -tree -filenames
#
# it adds filenames to the tree. Getting this information is slow:
#
@@ -58,7 +58,7 @@
#
# When run as:
#
-# $ git-verify-pack -v | packinfo.pl -dump
+# $ git verify-pack -v | packinfo.pl -dump
#
# it prints out "sha1 size pathsize depth" for each sha1 in lexical
# order.
@@ -106,7 +106,7 @@ while (<STDIN>) {
}
if ($filenames && ($tree || $dump)) {
- open(NAMES, "git-name-rev --all|");
+ open(NAMES, "git name-rev --all|");
while (<NAMES>) {
if (/^(\S+)\s+(.*)$/) {
my ($sha1, $name) = ($1, $2);
@@ -117,7 +117,7 @@ if ($filenames && ($tree || $dump)) {
for my $commit (@commits) {
my $name = $names{$commit};
- open(TREE, "git-ls-tree -t -r $commit|");
+ open(TREE, "git ls-tree -t -r $commit|");
print STDERR "Plumbing tree $name\n";
while (<TREE>) {
if (/^(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
diff --git a/csum-file.c b/csum-file.c
index 28389541a3..cfc1ac42b9 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -11,7 +11,7 @@
#include "progress.h"
#include "csum-file.h"
-static void sha1flush(struct sha1file *f, unsigned int count)
+static void flush(struct sha1file *f, unsigned int count)
{
void *buf = f->buffer;
@@ -32,22 +32,28 @@ static void sha1flush(struct sha1file *f, unsigned int count)
}
}
-int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
+void sha1flush(struct sha1file *f)
{
- int fd;
unsigned offset = f->offset;
if (offset) {
SHA1_Update(&f->ctx, f->buffer, offset);
- sha1flush(f, offset);
+ flush(f, offset);
f->offset = 0;
}
+}
+
+int sha1close(struct sha1file *f, unsigned char *result, unsigned int flags)
+{
+ int fd;
+
+ sha1flush(f);
SHA1_Final(f->buffer, &f->ctx);
if (result)
hashcpy(result, f->buffer);
if (flags & (CSUM_CLOSE | CSUM_FSYNC)) {
/* write checksum and close fd */
- sha1flush(f, 20);
+ flush(f, 20);
if (flags & CSUM_FSYNC)
fsync_or_die(f->fd, f->name);
if (close(f->fd))
@@ -76,7 +82,7 @@ int sha1write(struct sha1file *f, void *buf, unsigned int count)
left -= nr;
if (!left) {
SHA1_Update(&f->ctx, f->buffer, offset);
- sha1flush(f, offset);
+ flush(f, offset);
offset = 0;
}
f->offset = offset;
diff --git a/csum-file.h b/csum-file.h
index 72c9487f4f..01f13b5501 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -24,6 +24,7 @@ extern struct sha1file *sha1fd(int fd, const char *name);
extern struct sha1file *sha1fd_throughput(int fd, const char *name, struct progress *tp);
extern int sha1close(struct sha1file *, unsigned char *, unsigned int);
extern int sha1write(struct sha1file *, void *, unsigned int);
+extern void sha1flush(struct sha1file *f);
extern void crc32_begin(struct sha1file *);
extern uint32_t crc32_end(struct sha1file *);
diff --git a/diff.c b/diff.c
index 9385a36f1e..f91f256c56 100644
--- a/diff.c
+++ b/diff.c
@@ -94,32 +94,37 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val
* to define a customized regexp to find the beginning of a function to
* be used for hunk header lines of "diff -p" style output.
*/
-static struct funcname_pattern {
+struct funcname_pattern_entry {
char *name;
char *pattern;
- struct funcname_pattern *next;
+ int cflags;
+};
+static struct funcname_pattern_list {
+ struct funcname_pattern_list *next;
+ struct funcname_pattern_entry e;
} *funcname_pattern_list;
-static int parse_funcname_pattern(const char *var, const char *ep, const char *value)
+static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags)
{
const char *name;
int namelen;
- struct funcname_pattern *pp;
+ struct funcname_pattern_list *pp;
name = var + 5; /* "diff." */
namelen = ep - name;
for (pp = funcname_pattern_list; pp; pp = pp->next)
- if (!strncmp(pp->name, name, namelen) && !pp->name[namelen])
+ if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen])
break;
if (!pp) {
pp = xcalloc(1, sizeof(*pp));
- pp->name = xmemdupz(name, namelen);
+ pp->e.name = xmemdupz(name, namelen);
pp->next = funcname_pattern_list;
funcname_pattern_list = pp;
}
- free(pp->pattern);
- pp->pattern = xstrdup(value);
+ free(pp->e.pattern);
+ pp->e.pattern = xstrdup(value);
+ pp->e.cflags = cflags;
return 0;
}
@@ -182,7 +187,13 @@ int git_diff_basic_config(const char *var, const char *value, void *cb)
if (!strcmp(ep, ".funcname")) {
if (!value)
return config_error_nonbool(var);
- return parse_funcname_pattern(var, ep, value);
+ return parse_funcname_pattern(var, ep, value,
+ 0);
+ } else if (!strcmp(ep, ".xfuncname")) {
+ if (!value)
+ return config_error_nonbool(var);
+ return parse_funcname_pattern(var, ep, value,
+ REG_EXTENDED);
}
}
}
@@ -1377,39 +1388,40 @@ int diff_filespec_is_binary(struct diff_filespec *one)
return one->is_binary;
}
-static const char *funcname_pattern(const char *ident)
+static const struct funcname_pattern_entry *funcname_pattern(const char *ident)
{
- struct funcname_pattern *pp;
+ struct funcname_pattern_list *pp;
for (pp = funcname_pattern_list; pp; pp = pp->next)
- if (!strcmp(ident, pp->name))
- return pp->pattern;
+ if (!strcmp(ident, pp->e.name))
+ return &pp->e;
return NULL;
}
-static struct builtin_funcname_pattern {
- const char *name;
- const char *pattern;
-} builtin_funcname_pattern[] = {
- { "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|"
- "new\\|return\\|switch\\|throw\\|while\\)\n"
- "^[ ]*\\(\\([ ]*"
- "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}"
- "[ ]*([^;]*\\)$" },
- { "pascal", "^\\(\\(procedure\\|function\\|constructor\\|"
- "destructor\\|interface\\|implementation\\|"
- "initialization\\|finalization\\)[ \t]*.*\\)$"
- "\\|"
- "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$"
- },
- { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" },
- { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" },
- { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" },
+static const struct funcname_pattern_entry builtin_funcname_pattern[] = {
+ { "java",
+ "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"
+ "^[ \t]*(([ \t]*[A-Za-z_][A-Za-z_0-9]*){2,}[ \t]*\\([^;]*)$",
+ REG_EXTENDED },
+ { "pascal",
+ "^((procedure|function|constructor|destructor|interface|"
+ "implementation|initialization|finalization)[ \t]*.*)$"
+ "|"
+ "^(.*=[ \t]*(class|record).*)$",
+ REG_EXTENDED },
+ { "bibtex", "(@[a-zA-Z]{1,}[ \t]*\\{{0,1}[ \t]*[^ \t\"@',\\#}{~%]*).*$",
+ REG_EXTENDED },
+ { "tex",
+ "^(\\\\((sub)*section|chapter|part)\\*{0,1}\\{.*)$",
+ REG_EXTENDED },
+ { "ruby", "^[ \t]*((class|module|def)[ \t].*)$",
+ REG_EXTENDED },
};
-static const char *diff_funcname_pattern(struct diff_filespec *one)
+static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one)
{
- const char *ident, *pattern;
+ const char *ident;
+ const struct funcname_pattern_entry *pe;
int i;
diff_filespec_check_attr(one);
@@ -1424,9 +1436,9 @@ static const char *diff_funcname_pattern(struct diff_filespec *one)
return funcname_pattern("default");
/* Look up custom "funcname.$ident" regexp from config. */
- pattern = funcname_pattern(ident);
- if (pattern)
- return pattern;
+ pe = funcname_pattern(ident);
+ if (pe)
+ return pe;
/*
* And define built-in fallback patterns here. Note that
@@ -1434,7 +1446,7 @@ static const char *diff_funcname_pattern(struct diff_filespec *one)
*/
for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++)
if (!strcmp(ident, builtin_funcname_pattern[i].name))
- return builtin_funcname_pattern[i].pattern;
+ return &builtin_funcname_pattern[i];
return NULL;
}
@@ -1453,6 +1465,10 @@ static void builtin_diff(const char *name_a,
const char *set = diff_get_color_opt(o, DIFF_METAINFO);
const char *reset = diff_get_color_opt(o, DIFF_RESET);
+ /* Never use a non-valid filename anywhere if at all possible */
+ name_a = DIFF_FILE_VALID(one) ? name_a : name_b;
+ name_b = DIFF_FILE_VALID(two) ? name_b : name_a;
+
a_one = quote_two(o->a_prefix, name_a + (*name_a == '/'));
b_two = quote_two(o->b_prefix, name_b + (*name_b == '/'));
lbl[0] = DIFF_FILE_VALID(one) ? a_one : "/dev/null";
@@ -1512,11 +1528,11 @@ static void builtin_diff(const char *name_a,
xdemitconf_t xecfg;
xdemitcb_t ecb;
struct emit_callback ecbdata;
- const char *funcname_pattern;
+ const struct funcname_pattern_entry *pe;
- funcname_pattern = diff_funcname_pattern(one);
- if (!funcname_pattern)
- funcname_pattern = diff_funcname_pattern(two);
+ pe = diff_funcname_pattern(one);
+ if (!pe)
+ pe = diff_funcname_pattern(two);
memset(&xecfg, 0, sizeof(xecfg));
memset(&ecbdata, 0, sizeof(ecbdata));
@@ -1528,8 +1544,8 @@ static void builtin_diff(const char *name_a,
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
xecfg.ctxlen = o->context;
xecfg.flags = XDL_EMIT_FUNCNAMES;
- if (funcname_pattern)
- xdiff_set_find_func(&xecfg, funcname_pattern);
+ if (pe)
+ xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags);
if (!diffopts)
;
else if (!prefixcmp(diffopts, "--unified="))
diff --git a/dir.c b/dir.c
index 109e05b013..cfaa28ff23 100644
--- a/dir.c
+++ b/dir.c
@@ -837,3 +837,23 @@ void setup_standard_excludes(struct dir_struct *dir)
if (excludes_file && !access(excludes_file, R_OK))
add_excludes_from_file(dir, excludes_file);
}
+
+int remove_path(const char *name)
+{
+ char *slash;
+
+ if (unlink(name) && errno != ENOENT)
+ return -1;
+
+ slash = strrchr(name, '/');
+ if (slash) {
+ char *dirs = xstrdup(name);
+ slash = dirs + (slash - name);
+ do {
+ *slash = '\0';
+ } while (rmdir(dirs) && (slash = strrchr(dirs, '/')));
+ free(dirs);
+ }
+ return 0;
+}
+
diff --git a/dir.h b/dir.h
index 2df15defb6..278ee42295 100644
--- a/dir.h
+++ b/dir.h
@@ -81,4 +81,7 @@ extern int is_inside_dir(const char *dir);
extern void setup_standard_excludes(struct dir_struct *dir);
extern int remove_dir_recursively(struct strbuf *path, int only_empty);
+/* tries to remove the path with empty directories along it, ignores ENOENT */
+extern int remove_path(const char *path);
+
#endif
diff --git a/fast-import.c b/fast-import.c
index d85b3a561f..5473cd4d62 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -816,7 +816,7 @@ static void start_packfile(void)
int pack_fd;
snprintf(tmpfile, sizeof(tmpfile),
- "%s/tmp_pack_XXXXXX", get_object_directory());
+ "%s/pack/tmp_pack_XXXXXX", get_object_directory());
pack_fd = xmkstemp(tmpfile);
p = xcalloc(1, sizeof(*p) + strlen(tmpfile) + 2);
strcpy(p->pack_name, tmpfile);
@@ -878,7 +878,7 @@ static char *create_index(void)
}
snprintf(tmpfile, sizeof(tmpfile),
- "%s/tmp_idx_XXXXXX", get_object_directory());
+ "%s/pack/tmp_idx_XXXXXX", get_object_directory());
idx_fd = xmkstemp(tmpfile);
f = sha1fd(idx_fd, tmpfile);
sha1write(f, array, 256 * sizeof(int));
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index edb6ec6ed0..124cb5846b 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -65,6 +65,16 @@ output () {
esac
}
+run_pre_rebase_hook () {
+ if test -x "$GIT_DIR/hooks/pre-rebase"
+ then
+ "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
+ echo >&2 "The pre-rebase hook refused to rebase."
+ exit 1
+ }
+ fi
+}
+
require_clean_work_tree () {
# test if working tree is dirty
git rev-parse --verify HEAD > /dev/null &&
@@ -267,7 +277,7 @@ do_next () {
"$DOTEST"/amend || exit
read command sha1 rest < "$TODO"
case "$command" in
- '#'*|'')
+ '#'*|''|noop)
mark_action_done
;;
pick|p)
@@ -304,23 +314,28 @@ do_next () {
mark_action_done
make_squash_message $sha1 > "$MSG"
+ failed=f
+ author_script=$(get_author_ident_from_commit HEAD)
+ output git reset --soft HEAD^
+ pick_one -n $sha1 || failed=t
case "$(peek_next_command)" in
squash|s)
EDIT_COMMIT=
USE_OUTPUT=output
+ MSG_OPT=-F
+ MSG_FILE="$MSG"
cp "$MSG" "$SQUASH_MSG"
;;
*)
EDIT_COMMIT=-e
USE_OUTPUT=
+ MSG_OPT=
+ MSG_FILE=
rm -f "$SQUASH_MSG" || exit
+ cp "$MSG" "$GIT_DIR"/SQUASH_MSG
+ rm -f "$GIT_DIR"/MERGE_MSG || exit
;;
esac
-
- failed=f
- author_script=$(get_author_ident_from_commit HEAD)
- output git reset --soft HEAD^
- pick_one -n $sha1 || failed=t
echo "$author_script" > "$DOTEST"/author-script
if test $failed = f
then
@@ -329,7 +344,7 @@ do_next () {
GIT_AUTHOR_NAME="$GIT_AUTHOR_NAME" \
GIT_AUTHOR_EMAIL="$GIT_AUTHOR_EMAIL" \
GIT_AUTHOR_DATE="$GIT_AUTHOR_DATE" \
- $USE_OUTPUT git commit --no-verify -F "$MSG" $EDIT_COMMIT || failed=t
+ $USE_OUTPUT git commit --no-verify $MSG_OPT "$MSG_FILE" $EDIT_COMMIT || failed=t
fi
if test $failed = t
then
@@ -507,6 +522,7 @@ first and then run 'git rebase --continue' again."
;;
--)
shift
+ run_pre_rebase_hook ${1+"$@"}
test $# -eq 1 -o $# -eq 2 || usage
test -d "$DOTEST" &&
die "Interactive rebase already started"
@@ -568,6 +584,7 @@ first and then run 'git rebase --continue' again."
--abbrev=7 --reverse --left-right --cherry-pick \
$UPSTREAM...$HEAD | \
sed -n "s/^>/pick /p" > "$TODO"
+ test -s "$TODO" || echo noop >> "$TODO"
cat >> "$TODO" << EOF
# Rebase $SHORTUPSTREAM..$SHORTHEAD onto $SHORTONTO
diff --git a/git-rebase.sh b/git-rebase.sh
index 528b604cd5..a30d40c005 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -144,6 +144,16 @@ is_interactive () {
done && test -n "$1"
}
+run_pre_rebase_hook () {
+ if test -x "$GIT_DIR/hooks/pre-rebase"
+ then
+ "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
+ echo >&2 "The pre-rebase hook refused to rebase."
+ exit 1
+ }
+ fi
+}
+
test -f "$GIT_DIR"/rebase-apply/applying &&
die 'It looks like git-am is in progress. Cannot rebase.'
@@ -320,13 +330,7 @@ onto_name=${newbase-"$upstream_name"}
onto=$(git rev-parse --verify "${onto_name}^0") || exit
# If a hook exists, give it a chance to interrupt
-if test -x "$GIT_DIR/hooks/pre-rebase"
-then
- "$GIT_DIR/hooks/pre-rebase" ${1+"$@"} || {
- echo >&2 "The pre-rebase hook refused to rebase."
- exit 1
- }
-fi
+run_pre_rebase_hook ${1+"$@"}
# If the branch to rebase is given, that is the branch we will rebase
# $branch_name -- branch being rebased, or HEAD (already detached)
diff --git a/git-stash.sh b/git-stash.sh
index d799c76378..b9ace99704 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -144,17 +144,16 @@ show_stash () {
then
flags=--stat
fi
- s=$(git rev-parse --revs-only --no-flags --default $ref_stash "$@")
- w_commit=$(git rev-parse --verify "$s") &&
- b_commit=$(git rev-parse --verify "$s^") &&
+ w_commit=$(git rev-parse --verify --default $ref_stash "$@") &&
+ b_commit=$(git rev-parse --verify "$w_commit^") &&
git diff $flags $b_commit $w_commit
}
apply_stash () {
git update-index -q --refresh &&
git diff-files --quiet --ignore-submodules ||
- die 'Cannot restore on top of a dirty state'
+ die 'Cannot apply to a dirty working tree, please stage your changes'
unstash_index=
case "$1" in
@@ -169,7 +168,7 @@ apply_stash () {
# stash records the work tree, and is a merge between the
# base commit (first parent) and the index tree (second parent).
- s=$(git rev-parse --revs-only --no-flags --default $ref_stash "$@") &&
+ s=$(git rev-parse --verify --default $ref_stash "$@") &&
w_tree=$(git rev-parse --verify "$s:") &&
b_tree=$(git rev-parse --verify "$s^1:") &&
i_tree=$(git rev-parse --verify "$s^2:") ||
@@ -229,7 +228,7 @@ drop_stash () {
shift
fi
# Verify supplied argument looks like a stash entry
- s=$(git rev-parse --revs-only --no-flags "$@") &&
+ s=$(git rev-parse --verify "$@") &&
git rev-parse --verify "$s:" > /dev/null 2>&1 &&
git rev-parse --verify "$s^1:" > /dev/null 2>&1 &&
git rev-parse --verify "$s^2:" > /dev/null 2>&1 ||
diff --git a/git-submodule.sh b/git-submodule.sh
index b40f876a2c..5888735e4f 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -185,7 +185,7 @@ cmd_add()
else
module_clone "$path" "$realrepo" || exit
- (unset GIT_DIR; cd "$path" && git checkout -q ${branch:+-b "$branch" "origin/$branch"}) ||
+ (unset GIT_DIR; cd "$path" && git checkout -f -q ${branch:+-b "$branch" "origin/$branch"}) ||
die "Unable to checkout submodule '$path'"
fi
@@ -311,8 +311,13 @@ cmd_update()
if test "$subsha1" != "$sha1"
then
+ force=
+ if test -z "$subsha1"
+ then
+ force="-f"
+ fi
(unset GIT_DIR; cd "$path" && git-fetch &&
- git-checkout -q "$sha1") ||
+ git-checkout $force -q "$sha1") ||
die "Unable to checkout '$sha1' in submodule path '$path'"
say "Submodule path '$path': checked out '$sha1'"
diff --git a/git-svn.perl b/git-svn.perl
index 7c7fc39483..33e1b503c4 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -2571,7 +2571,7 @@ sub set_tree {
my ($self, $tree) = (shift, shift);
my $log_entry = ::get_commit_entry($tree);
unless ($self->{last_rev}) {
- fatal("Must have an existing revision to commit");
+ ::fatal("Must have an existing revision to commit");
}
my %ed_opts = ( r => $self->{last_rev},
log => $log_entry->{log},
diff --git a/git.c b/git.c
index fdb0f71019..5582c515ac 100644
--- a/git.c
+++ b/git.c
@@ -162,6 +162,8 @@ static int handle_alias(int *argcp, const char ***argv)
alias_string + 1, alias_command);
}
count = split_cmdline(alias_string, &new_argv);
+ if (count < 0)
+ die("Bad alias.%s string", alias_command);
option_count = handle_options(&new_argv, &count, &envchanged);
if (envchanged)
die("alias '%s' changes environment variables\n"
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 269f1125d9..eae5084c66 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -27,6 +27,13 @@ our $version = "++GIT_VERSION++";
our $my_url = $cgi->url();
our $my_uri = $cgi->url(-absolute => 1);
+# if we're called with PATH_INFO, we have to strip that
+# from the URL to find our real URL
+if (my $path_info = $ENV{"PATH_INFO"}) {
+ $my_url =~ s,\Q$path_info\E$,,;
+ $my_uri =~ s,\Q$path_info\E$,,;
+}
+
# core git executable to use
# this can just be "git" if your webserver has a sensible PATH
our $GIT = "++GIT_BINDIR++/git";
@@ -4414,6 +4421,7 @@ sub git_tree {
$hash = $hash_base;
}
}
+ die_error(404, "No such tree") unless defined($hash);
$/ = "\0";
open my $fd, "-|", git_cmd(), "ls-tree", '-z', $hash
or die_error(500, "Open git-ls-tree failed");
@@ -4454,8 +4462,8 @@ sub git_tree {
if ($basedir ne '' && substr($basedir, -1) ne '/') {
$basedir .= '/';
}
+ git_print_page_path($file_name, 'tree', $hash_base);
}
- git_print_page_path($file_name, 'tree', $hash_base);
print "<div class=\"page_body\">\n";
print "<table class=\"tree\">\n";
my $alternate = 1;
diff --git a/index-pack.c b/index-pack.c
index a6e91fe3ba..2a366206a4 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -172,7 +172,7 @@ static char *open_pack_file(char *pack_name)
if (!pack_name) {
static char tmpfile[PATH_MAX];
snprintf(tmpfile, sizeof(tmpfile),
- "%s/tmp_pack_XXXXXX", get_object_directory());
+ "%s/pack/tmp_pack_XXXXXX", get_object_directory());
output_fd = xmkstemp(tmpfile);
pack_name = xstrdup(tmpfile);
} else
@@ -365,8 +365,11 @@ static void *get_data_from_pack(struct object_entry *obj)
data = src;
do {
ssize_t n = pread(pack_fd, data + rdy, len - rdy, from + rdy);
- if (n <= 0)
+ if (n < 0)
die("cannot pread pack file: %s", strerror(errno));
+ if (!n)
+ die("premature end of pack file, %lu bytes missing",
+ len - rdy);
rdy += n;
} while (rdy < len);
data = xmalloc(obj->size);
@@ -704,6 +707,7 @@ static struct object_entry *append_obj_to_pack(struct sha1file *f,
obj[1].idx.offset = obj[0].idx.offset + n;
obj[1].idx.offset += write_compressed(f, buf, size);
obj[0].idx.crc32 = crc32_end(f);
+ sha1flush(f);
hashcpy(obj->idx.sha1, sha1);
return obj;
}
diff --git a/pack-write.c b/pack-write.c
index 939ed56362..3621f1dd32 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -45,7 +45,7 @@ char *write_idx_file(char *index_name, struct pack_idx_entry **objects,
if (!index_name) {
static char tmpfile[PATH_MAX];
snprintf(tmpfile, sizeof(tmpfile),
- "%s/tmp_idx_XXXXXX", get_object_directory());
+ "%s/pack/tmp_idx_XXXXXX", get_object_directory());
fd = xmkstemp(tmpfile);
index_name = xstrdup(tmpfile);
} else {
diff --git a/remote.c b/remote.c
index 105668f8a3..7688f3b04d 100644
--- a/remote.c
+++ b/remote.c
@@ -342,13 +342,14 @@ static int handle_config(const char *key, const char *value, void *cb)
if (prefixcmp(key, "remote."))
return 0;
name = key + 7;
+ if (*name == '/') {
+ warning("Config remote shorthand cannot begin with '/': %s",
+ name);
+ return 0;
+ }
subkey = strrchr(name, '.');
if (!subkey)
return error("Config with no key for remote %s", name);
- if (*subkey == '/') {
- warning("Config remote shorthand cannot begin with '/': %s", name);
- return 0;
- }
remote = make_remote(name, subkey - name);
if (!strcmp(subkey, ".mirror"))
remote->mirror = git_config_bool(key, value);
diff --git a/setup.c b/setup.c
index 2e3248a0c4..78a8041ff0 100644
--- a/setup.c
+++ b/setup.c
@@ -110,9 +110,7 @@ const char *prefix_path(const char *prefix, int len, const char *path)
if (strncmp(sanitized, work_tree, len) ||
(sanitized[len] != '\0' && sanitized[len] != '/')) {
error_out:
- error("'%s' is outside repository", orig);
- free(sanitized);
- return NULL;
+ die("'%s' is outside repository", orig);
}
if (sanitized[len] == '/')
len++;
@@ -216,10 +214,7 @@ const char **get_pathspec(const char *prefix, const char **pathspec)
prefixlen = prefix ? strlen(prefix) : 0;
while (*src) {
const char *p = prefix_path(prefix, prefixlen, *src);
- if (p)
- *(dst++) = p;
- else
- exit(128); /* error message already given */
+ *(dst++) = p;
src++;
}
*dst = NULL;
diff --git a/sha1_file.c b/sha1_file.c
index e2cb342a32..c78507152f 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2322,6 +2322,7 @@ int force_object_loose(const unsigned char *sha1, time_t mtime)
enum object_type type;
char hdr[32];
int hdrlen;
+ int ret;
if (has_loose_object(sha1))
return 0;
@@ -2329,7 +2330,10 @@ int force_object_loose(const unsigned char *sha1, time_t mtime)
if (!buf)
return error("cannot read sha1_file for %s", sha1_to_hex(sha1));
hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
- return write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
+ ret = write_loose_object(sha1, hdr, hdrlen, buf, len, mtime);
+ free(buf);
+
+ return ret;
}
int has_pack_index(const unsigned char *sha1)
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 620da5b320..5ac0a273a9 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -167,4 +167,36 @@ test_expect_success 'init with --template (blank)' '
! test -f template-blank/.git/info/exclude
'
+test_expect_success 'init --bare/--shared overrides system/global config' '
+ (
+ HOME="`pwd`" &&
+ export HOME &&
+ test_config="$HOME"/.gitconfig &&
+ unset GIT_CONFIG_NOGLOBAL &&
+ git config -f "$test_config" core.bare false &&
+ git config -f "$test_config" core.sharedRepository 0640 &&
+ mkdir init-bare-shared-override &&
+ cd init-bare-shared-override &&
+ git init --bare --shared=0666
+ ) &&
+ check_config init-bare-shared-override true unset &&
+ test x0666 = \
+ x`git config -f init-bare-shared-override/config core.sharedRepository`
+'
+
+test_expect_success 'init honors global core.sharedRepository' '
+ (
+ HOME="`pwd`" &&
+ export HOME &&
+ test_config="$HOME"/.gitconfig &&
+ unset GIT_CONFIG_NOGLOBAL &&
+ git config -f "$test_config" core.sharedRepository 0666 &&
+ mkdir shared-honor-global &&
+ cd shared-honor-global &&
+ git init
+ ) &&
+ test x0666 = \
+ x`git config -f shared-honor-global/.git/config core.sharedRepository`
+'
+
test_done
diff --git a/t/t0024-crlf-archive.sh b/t/t0024-crlf-archive.sh
index e5330395fc..e5330395fc 100644..100755
--- a/t/t0024-crlf-archive.sh
+++ b/t/t0024-crlf-archive.sh
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 64567fb94d..11b82f43dd 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -741,4 +741,14 @@ test_expect_success 'symlinked configuration' '
'
+test_expect_success 'check split_cmdline return' "
+ git config alias.split-cmdline-fix 'echo \"' &&
+ test_must_fail git split-cmdline-fix &&
+ echo foo > foo &&
+ git add foo &&
+ git commit -m 'initial commit' &&
+ git config branch.master.mergeoptions 'echo \"' &&
+ test_must_fail git merge master
+ "
+
test_done
diff --git a/t/t1301-shared-repo.sh b/t/t1301-shared-repo.sh
index dc85e8b60a..2275caa317 100755
--- a/t/t1301-shared-repo.sh
+++ b/t/t1301-shared-repo.sh
@@ -7,6 +7,9 @@ test_description='Test shared repository initialization'
. ./test-lib.sh
+# Remove a default ACL from the test dir if possible.
+setfacl -k . 2>/dev/null
+
# User must have read permissions to the repo -> failure on --shared=0400
test_expect_success 'shared = 0400 (faulty permission u-w)' '
mkdir sub && (
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index de0cdb1cf4..0de613dc53 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -535,4 +535,15 @@ test_expect_success 'reset and bind merge' '
'
+test_expect_success 'merge removes empty directories' '
+
+ git reset --hard master &&
+ git checkout -b rm &&
+ git rm d/e &&
+ git commit -mremoved-d/e &&
+ git checkout master &&
+ git merge -s recursive rm &&
+ test_must_fail test -d d
+'
+
test_done
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index e0ded197ec..7d10a27f1d 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -419,4 +419,15 @@ test_expect_success 'rebase with a file named HEAD in worktree' '
'
+test_expect_success 'do "noop" when there is nothing to cherry-pick' '
+
+ git checkout -b branch4 HEAD &&
+ GIT_EDITOR=: git commit --amend \
+ --author="Somebody else <somebody@else.com>"
+ test $(git rev-parse branch3) != $(git rev-parse branch4) &&
+ git rebase -i branch3 &&
+ test $(git rev-parse branch3) = $(git rev-parse branch4)
+
+'
+
test_done
diff --git a/t/t3409-rebase-hook.sh b/t/t3409-rebase-hook.sh
new file mode 100755
index 0000000000..bc93dda8fd
--- /dev/null
+++ b/t/t3409-rebase-hook.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='git rebase with its hook(s)'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+ echo hello >file &&
+ git add file &&
+ test_tick &&
+ git commit -m initial &&
+ echo goodbye >file &&
+ git add file &&
+ test_tick &&
+ git commit -m second &&
+ git checkout -b side HEAD^ &&
+ echo world >git &&
+ git add git &&
+ test_tick &&
+ git commit -m side &&
+ git checkout master &&
+ git log --pretty=oneline --abbrev-commit --graph --all &&
+ git branch test side
+'
+
+test_expect_success 'rebase' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase master &&
+ test "z$(cat git)" = zworld
+'
+
+test_expect_success 'rebase -i' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase -i master &&
+ test "z$(cat git)" = zworld
+'
+
+test_expect_success 'setup pre-rebase hook' '
+ mkdir -p .git/hooks &&
+ cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+echo "\$1,\$2" >.git/PRE-REBASE-INPUT
+EOF
+ chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook gets correct input (1)' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase master &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
+
+'
+
+test_expect_success 'pre-rebase hook gets correct input (2)' '
+ git checkout test &&
+ git reset --hard side &&
+ git rebase master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (3)' '
+ git checkout test &&
+ git reset --hard side &&
+ git checkout master &&
+ git rebase master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (4)' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase -i master &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,
+
+'
+
+test_expect_success 'pre-rebase hook gets correct input (5)' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true git rebase -i master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'pre-rebase hook gets correct input (6)' '
+ git checkout test &&
+ git reset --hard side &&
+ git checkout master &&
+ EDITOR=true git rebase -i master test &&
+ test "z$(cat git)" = zworld &&
+ test "z$(cat .git/PRE-REBASE-INPUT)" = zmaster,test
+'
+
+test_expect_success 'setup pre-rebase hook that fails' '
+ mkdir -p .git/hooks &&
+ cat >.git/hooks/pre-rebase <<EOF &&
+#!$SHELL_PATH
+false
+EOF
+ chmod +x .git/hooks/pre-rebase
+'
+
+test_expect_success 'pre-rebase hook stops rebase (1)' '
+ git checkout test &&
+ git reset --hard side &&
+ test_must_fail git rebase master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test 0 = $(git rev-list HEAD...side | wc -l)
+'
+
+test_expect_success 'pre-rebase hook stops rebase (2)' '
+ git checkout test &&
+ git reset --hard side &&
+ EDITOR=true test_must_fail git rebase -i master &&
+ test "z$(git symbolic-ref HEAD)" = zrefs/heads/test &&
+ test 0 = $(git rev-list HEAD...side | wc -l)
+'
+
+test_done
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 558c80edbf..66aca99fd3 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -219,14 +219,23 @@ test_expect_success 'Remove nonexistent file returns nonzero exit status' '
test_expect_success 'Call "rm" from outside the work tree' '
mkdir repo &&
- cd repo &&
- git init &&
- echo something > somefile &&
- git add somefile &&
- git commit -m "add a file" &&
- (cd .. &&
- git --git-dir=repo/.git --work-tree=repo rm somefile) &&
- test_must_fail git ls-files --error-unmatch somefile
+ (cd repo &&
+ git init &&
+ echo something > somefile &&
+ git add somefile &&
+ git commit -m "add a file" &&
+ (cd .. &&
+ git --git-dir=repo/.git --work-tree=repo rm somefile) &&
+ test_must_fail git ls-files --error-unmatch somefile)
+'
+
+test_expect_success 'refresh index before checking if it is up-to-date' '
+
+ git reset --hard &&
+ test-chmtime -86400 frotz/nitfol &&
+ git rm frotz/nitfol &&
+ test ! -f frotz/nitfol
+
'
test_done
diff --git a/t/t4012-diff-binary.sh b/t/t4012-diff-binary.sh
index 64c372a025..eac12712db 100755
--- a/t/t4012-diff-binary.sh
+++ b/t/t4012-diff-binary.sh
@@ -77,4 +77,25 @@ test_expect_success 'apply binary patch' \
tree1=`git write-tree` &&
test "$tree1" = "$tree0"'
+q_to_nul() {
+ perl -pe 'y/Q/\000/'
+}
+
+nul_to_q() {
+ perl -pe 'y/\000/Q/'
+}
+
+test_expect_success 'diff --no-index with binary creation' '
+ echo Q | q_to_nul >binary &&
+ (:# hide error code from diff, which just indicates differences
+ git diff --binary --no-index /dev/null binary >current ||
+ true
+ ) &&
+ rm binary &&
+ git apply --binary <current &&
+ echo Q >expected &&
+ nul_to_q <binary >actual &&
+ test_cmp expected actual
+'
+
test_done
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 18bcd9713d..398bf4b5d8 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -32,7 +32,18 @@ EOF
sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java
+builtin_patterns="bibtex java pascal ruby tex"
+for p in $builtin_patterns
+do
+ test_expect_success "builtin $p pattern compiles" '
+ echo "*.java diff=$p" > .gitattributes &&
+ ! ( git diff --no-index Beer.java Beer-correct.java 2>&1 |
+ grep "fatal" > /dev/null )
+ '
+done
+
test_expect_success 'default behaviour' '
+ rm -f .gitattributes &&
git diff --no-index Beer.java Beer-correct.java |
grep "^@@.*@@ public class Beer"
'
@@ -54,11 +65,18 @@ test_expect_success 'custom pattern' '
test_expect_success 'last regexp must not be negated' '
git config diff.java.funcname "!static" &&
- test_must_fail git diff --no-index Beer.java Beer-correct.java
+ git diff --no-index Beer.java Beer-correct.java 2>&1 |
+ grep "fatal: Last expression must not be negated:"
+'
+
+test_expect_success 'pattern which matches to end of line' '
+ git config diff.java.funcname "Beer$" &&
+ git diff --no-index Beer.java Beer-correct.java |
+ grep "^@@.*@@ Beer"
'
test_expect_success 'alternation in pattern' '
- git config diff.java.funcname "^[ ]*\\(\\(public\\|static\\).*\\)$"
+ git config diff.java.xfuncname "^[ ]*((public|static).*)$" &&
git diff --no-index Beer.java Beer-correct.java |
grep "^@@.*@@ public static void main("
'
diff --git a/t/t4128-apply-root.sh b/t/t4128-apply-root.sh
index 2dd0c75f96..8f6aea48d8 100755
--- a/t/t4128-apply-root.sh
+++ b/t/t4128-apply-root.sh
@@ -40,4 +40,56 @@ test_expect_success 'apply --directory -p (2) ' '
'
+cat > patch << EOF
+diff --git a/newfile b/newfile
+new file mode 100644
+index 0000000..d95f3ad
+--- /dev/null
++++ b/newfile
+@@ -0,0 +1 @@
++content
+EOF
+
+test_expect_success 'apply --directory (new file)' '
+ git reset --hard initial &&
+ git apply --directory=some/sub/dir/ --index patch &&
+ test content = $(git show :some/sub/dir/newfile) &&
+ test content = $(cat some/sub/dir/newfile)
+'
+
+cat > patch << EOF
+diff --git a/delfile b/delfile
+deleted file mode 100644
+index d95f3ad..0000000
+--- a/delfile
++++ /dev/null
+@@ -1 +0,0 @@
+-content
+EOF
+
+test_expect_success 'apply --directory (delete file)' '
+ git reset --hard initial &&
+ echo content >some/sub/dir/delfile &&
+ git add some/sub/dir/delfile &&
+ git apply --directory=some/sub/dir/ --index patch &&
+ ! (git ls-files | grep delfile)
+'
+
+cat > patch << 'EOF'
+diff --git "a/qu\157tefile" "b/qu\157tefile"
+new file mode 100644
+index 0000000..d95f3ad
+--- /dev/null
++++ "b/qu\157tefile"
+@@ -0,0 +1 @@
++content
+EOF
+
+test_expect_success 'apply --directory (quoted filename)' '
+ git reset --hard initial &&
+ git apply --directory=some/sub/dir/ --index patch &&
+ test content = $(git show :some/sub/dir/quotefile) &&
+ test content = $(cat some/sub/dir/quotefile)
+'
+
test_done
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 94bc556cb2..5abce3119b 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -507,4 +507,30 @@ test_expect_success 'in-index merge' '
test_debug 'gitk --all'
+cat >expected <<EOF
+Merge branch 'c5' (early part)
+EOF
+
+test_expect_success 'merge early part of c2' '
+ git reset --hard c3 &&
+ echo c4 > c4.c &&
+ git add c4.c &&
+ git commit -m c4 &&
+ git tag c4 &&
+ echo c5 > c5.c &&
+ git add c5.c &&
+ git commit -m c5 &&
+ git tag c5 &&
+ git reset --hard c3 &&
+ echo c6 > c6.c &&
+ git add c6.c &&
+ git commit -m c6 &&
+ git tag c6 &&
+ git merge c5~1 &&
+ git show -s --pretty=format:%s HEAD > actual &&
+ test_cmp actual expected
+'
+
+test_debug 'gitk --all'
+
test_done
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index ae7082be1d..d8f278ffee 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -503,6 +503,55 @@ test_expect_success \
test_debug 'cat gitweb.log'
# ----------------------------------------------------------------------
+# path_info links
+test_expect_success \
+ 'path_info: project' \
+ 'gitweb_run "" "/.git"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch' \
+ 'gitweb_run "" "/.git/b"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:file' \
+ 'gitweb_run "" "/.git/master:file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:dir/' \
+ 'gitweb_run "" "/.git/master:foo/"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:file (non-existent)' \
+ 'gitweb_run "" "/.git/master:non-existent"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/branch:dir/ (non-existent)' \
+ 'gitweb_run "" "/.git/master:non-existent/"'
+test_debug 'cat gitweb.log'
+
+
+test_expect_success \
+ 'path_info: project/branch:/file' \
+ 'gitweb_run "" "/.git/master:/file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/:/file (implicit HEAD)' \
+ 'gitweb_run "" "/.git/:/file"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'path_info: project/:/ (implicit HEAD, top tree)' \
+ 'gitweb_run "" "/.git/:/"'
+test_debug 'cat gitweb.log'
+
+
+# ----------------------------------------------------------------------
# feed generation
test_expect_success \
diff --git a/t/test-lib.sh b/t/test-lib.sh
index 11c027571b..689ac2f4b4 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -112,8 +112,9 @@ if test -n "$color"; then
*) test -n "$quiet" && return;;
esac
shift
- echo "* $*"
+ printf "* %s" "$*"
tput sgr0
+ echo
)
}
else
diff --git a/transport.c b/transport.c
index 71433d9997..35cac441f8 100644
--- a/transport.c
+++ b/transport.c
@@ -643,8 +643,8 @@ static int fetch_refs_via_pack(struct transport *transport,
args.use_thin_pack = data->thin;
args.include_tag = data->followtags;
args.verbose = (transport->verbose > 0);
- args.quiet = args.no_progress = (transport->verbose < 0);
- args.no_progress = !isatty(1);
+ args.quiet = (transport->verbose < 0);
+ args.no_progress = args.quiet || !isatty(1);
args.depth = data->depth;
for (i = 0; i < nr_heads; i++)
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 61dc5c5470..3bf83f81e3 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -179,11 +179,21 @@ struct ff_regs {
static long ff_regexp(const char *line, long len,
char *buffer, long buffer_size, void *priv)
{
- char *line_buffer = xstrndup(line, len); /* make NUL terminated */
+ char *line_buffer;
struct ff_regs *regs = priv;
regmatch_t pmatch[2];
int result = 0, i;
+ /* Exclude terminating newline (and cr) from matching */
+ if (len > 0 && line[len-1] == '\n') {
+ if (len > 1 && line[len-2] == '\r')
+ len -= 2;
+ else
+ len--;
+ }
+
+ line_buffer = xstrndup(line, len); /* make NUL terminated */
+
for (i = 0; i < regs->nr; i++) {
struct ff_reg *reg = regs->array + i;
if (reg->negate ^ !!regexec(&reg->re,
@@ -206,7 +216,7 @@ static long ff_regexp(const char *line, long len,
return result;
}
-void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value)
+void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value, int cflags)
{
int i;
struct ff_regs *regs;
@@ -231,7 +241,7 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value)
expression = buffer = xstrndup(value, ep - value);
else
expression = value;
- if (regcomp(&reg->re, expression, 0))
+ if (regcomp(&reg->re, expression, cflags))
die("Invalid regexp to look for hunk header: %s", expression);
free(buffer);
value = ep + 1;
diff --git a/xdiff-interface.h b/xdiff-interface.h
index f7f791d96b..33cab9dd59 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -21,6 +21,6 @@ int parse_hunk_header(char *line, int len,
int read_mmfile(mmfile_t *ptr, const char *filename);
int buffer_is_binary(const char *ptr, unsigned long size);
-extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line);
+extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags);
#endif