summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt9
-rw-r--r--Documentation/git-init-db.txt51
-rw-r--r--Documentation/git-status.txt6
-rw-r--r--Documentation/tutorial-2.txt1
-rw-r--r--builtin-apply.c9
-rw-r--r--builtin-diff.c4
-rw-r--r--combine-diff.c50
-rw-r--r--diff.c6
-rw-r--r--git-compat-util.h6
-rw-r--r--help.c2
-rw-r--r--http-fetch.c2
-rw-r--r--index-pack.c2
-rw-r--r--local-fetch.c4
-rw-r--r--refs.c2
-rw-r--r--revision.c3
-rw-r--r--sha1_file.c2
-rw-r--r--sha1_name.c2
-rwxr-xr-xt/t4115-apply-symlink.sh49
-rw-r--r--verify-pack.c75
19 files changed, 208 insertions, 77 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index d89916bea7..ce722a2db0 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -83,9 +83,12 @@ core.repositoryFormatVersion::
version.
core.sharedRepository::
- If true, the repository is made shareable between several users
- in a group (making sure all the files and objects are group-writable).
- See gitlink:git-init-db[1]. False by default.
+ When 'group' (or 'true'), the repository is made shareable between
+ several users in a group (making sure all the files and objects are
+ group-writable). When 'all' (or 'world' or 'everybody'), the
+ repository will be readable by all users, additionally to being
+ group-shareable. When 'umask' (or 'false'), git will use permissions
+ reported by umask(2). See gitlink:git-init-db[1]. False by default.
core.warnAmbiguousRefs::
If true, git will warn you if the ref name you passed it is ambiguous
diff --git a/Documentation/git-init-db.txt b/Documentation/git-init-db.txt
index 0a4fc14b97..63cd5dab3f 100644
--- a/Documentation/git-init-db.txt
+++ b/Documentation/git-init-db.txt
@@ -8,17 +8,47 @@ git-init-db - Creates an empty git repository
SYNOPSIS
--------
-'git-init-db' [--template=<template_directory>] [--shared]
+'git-init-db' [--template=<template_directory>] [--shared[=<permissions>]]
OPTIONS
-------
+
+--
+
--template=<template_directory>::
- Provide the directory from which templates will be used.
- The default template directory is `/usr/share/git-core/templates`.
---shared::
- Specify that the git repository is to be shared amongst several users.
+Provide the directory from which templates will be used. The default template
+directory is `/usr/share/git-core/templates`.
+
+When specified, `<template_directory>` is used as the source of the template
+files rather than the default. The template files include some directory
+structure, some suggested "exclude patterns", and copies of non-executing
+"hook" files. The suggested patterns and hook files are all modifiable and
+extensible.
+
+--shared[={false|true|umask|group|all|world|everybody}]::
+
+Specify that the git repository is to be shared amongst several users. This
+allows users belonging to the same group to push into that
+repository. When specified, the config variable "core.sharedRepository" is
+set so that files and directories under `$GIT_DIR` are created with the
+requested permissions. When not specified, git will use permissions reported
+by umask(2).
+
+The option can have the following values, defaulting to 'group' if no value
+is given:
+
+ - 'umask' (or 'false'): Use permissions reported by umask(2). The default,
+ when `--shared` is not specified.
+
+ - 'group' (or 'true'): Make the repository group-writable, (and g+sx, since
+ the git group may be not the primary group of all users).
+
+ - 'all' (or 'world' or 'everybody'): Same as 'group', but make the repository
+ readable by all users.
+
+--
DESCRIPTION
@@ -29,12 +59,6 @@ template files.
An initial `HEAD` file that references the HEAD of the master branch
is also created.
-If `--template=<template_directory>` is specified, `<template_directory>`
-is used as the source of the template files rather than the default.
-The template files include some directory structure, some suggested
-"exclude patterns", and copies of non-executing "hook" files. The
-suggested patterns and hook files are all modifiable and extensible.
-
If the `$GIT_DIR` environment variable is set then it specifies a path
to use instead of `./.git` for the base of the repository.
@@ -42,11 +66,6 @@ If the object storage directory is specified via the `$GIT_OBJECT_DIRECTORY`
environment variable then the sha1 directories are created underneath -
otherwise the default `$GIT_DIR/objects` directory is used.
-A shared repository allows users belonging to the same group to push into that
-repository. When specifying `--shared` the config variable "core.sharedRepository"
-is set to 'true' so that directories under `$GIT_DIR` are made group writable
-(and g+sx, since the git group may be not the primary group of all users).
-
Running `git-init-db` in an existing repository is safe. It will not overwrite
things that are already there. The primary reason for rerunning `git-init-db`
is to pick up newly added templates.
diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index e446f4812e..ce7857e5a9 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -8,7 +8,7 @@ git-status - Show working tree status
SYNOPSIS
--------
-'git-status'
+'git-status' <options>...
DESCRIPTION
-----------
@@ -23,6 +23,10 @@ If there is no path that is different between the index file and
the current HEAD commit, the command exits with non-zero
status.
+The command takes the same set of options as `git-commit`; it
+shows what would be committed if the same options are given to
+`git-commit`.
+
OUTPUT
------
diff --git a/Documentation/tutorial-2.txt b/Documentation/tutorial-2.txt
index 894ca5e06f..2f4fe1217a 100644
--- a/Documentation/tutorial-2.txt
+++ b/Documentation/tutorial-2.txt
@@ -244,6 +244,7 @@ $ git ls-files --stage
$ git cat-file -t 513feba2
blob
$ git cat-file blob 513feba2
+hello world!
hello world, again
------------------------------------------------
diff --git a/builtin-apply.c b/builtin-apply.c
index f8c6763c74..be2c7152cd 100644
--- a/builtin-apply.c
+++ b/builtin-apply.c
@@ -1698,6 +1698,12 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
desc.buffer = buf;
if (apply_fragments(&desc, patch) < 0)
return -1;
+
+ /* NUL terminate the result */
+ if (desc.alloc <= desc.size)
+ desc.buffer = xrealloc(desc.buffer, desc.size + 1);
+ desc.buffer[desc.size] = 0;
+
patch->result = desc.buffer;
patch->resultsize = desc.size;
@@ -2040,6 +2046,9 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
int fd;
if (S_ISLNK(mode))
+ /* Although buf:size is counted string, it also is NUL
+ * terminated.
+ */
return symlink(buf, path);
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
if (fd < 0)
diff --git a/builtin-diff.c b/builtin-diff.c
index 1075855102..a090e298a5 100644
--- a/builtin-diff.c
+++ b/builtin-diff.c
@@ -253,7 +253,8 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format) {
rev.diffopt.output_format = DIFF_FORMAT_PATCH;
- diff_setup_done(&rev.diffopt);
+ if (diff_setup_done(&rev.diffopt) < 0)
+ die("diff_setup_done failed");
}
/* Do we have --cached and not have a pending object, then
@@ -348,6 +349,7 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
* A and B. We have ent[0] == merge-base, ent[1] == A,
* and ent[2] == B. Show diff between the base and B.
*/
+ ent[1] = ent[2];
return builtin_diff_tree(&rev, argc, argv, ent);
}
else
diff --git a/combine-diff.c b/combine-diff.c
index 919112bba9..ba8baca0ab 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -497,11 +497,17 @@ static void show_parent_lno(struct sline *sline, unsigned long l0, unsigned long
printf(" -%lu,%lu", l0, l1-l0);
}
-static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
+static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent,
+ int use_color)
{
unsigned long mark = (1UL<<num_parent);
int i;
unsigned long lno = 0;
+ const char *c_frag = diff_get_color(use_color, DIFF_FRAGINFO);
+ const char *c_new = diff_get_color(use_color, DIFF_FILE_NEW);
+ const char *c_old = diff_get_color(use_color, DIFF_FILE_OLD);
+ const char *c_plain = diff_get_color(use_color, DIFF_PLAIN);
+ const char *c_reset = diff_get_color(use_color, DIFF_RESET);
if (!cnt)
return; /* result deleted */
@@ -522,12 +528,13 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
rlines = hunk_end - lno;
if (cnt < hunk_end)
rlines--; /* pointing at the last delete hunk */
+ fputs(c_frag, stdout);
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
for (i = 0; i < num_parent; i++)
show_parent_lno(sline, lno, hunk_end, i);
printf(" +%lu,%lu ", lno+1, rlines);
for (i = 0; i <= num_parent; i++) putchar(combine_marker);
- putchar('\n');
+ printf("%s\n", c_reset);
while (lno < hunk_end) {
struct lline *ll;
int j;
@@ -535,18 +542,23 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
sl = &sline[lno++];
ll = sl->lost_head;
while (ll) {
+ fputs(c_old, stdout);
for (j = 0; j < num_parent; j++) {
if (ll->parent_map & (1UL<<j))
putchar('-');
else
putchar(' ');
}
- puts(ll->line);
+ printf("%s%s\n", ll->line, c_reset);
ll = ll->next;
}
if (cnt < lno)
break;
p_mask = 1;
+ if (!(sl->flag & (mark-1)))
+ fputs(c_plain, stdout);
+ else
+ fputs(c_new, stdout);
for (j = 0; j < num_parent; j++) {
if (p_mask & sl->flag)
putchar('+');
@@ -554,7 +566,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent)
putchar(' ');
p_mask <<= 1;
}
- printf("%.*s\n", sl->len, sl->bol);
+ printf("%.*s%s\n", sl->len, sl->bol, c_reset);
}
}
}
@@ -586,14 +598,15 @@ static void reuse_combine_diff(struct sline *sline, unsigned long cnt,
sline->p_lno[i] = sline->p_lno[j];
}
-static void dump_quoted_path(const char *prefix, const char *path)
+static void dump_quoted_path(const char *prefix, const char *path,
+ const char *c_meta, const char *c_reset)
{
- fputs(prefix, stdout);
+ printf("%s%s", c_meta, prefix);
if (quote_c_style(path, NULL, NULL, 0))
quote_c_style(path, NULL, stdout, 0);
else
printf("%s", path);
- putchar('\n');
+ printf("%s\n", c_reset);
}
static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
@@ -699,18 +712,22 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
if (show_hunks || mode_differs || working_tree_file) {
const char *abb;
+ int use_color = opt->color_diff;
+ const char *c_meta = diff_get_color(use_color, DIFF_METAINFO);
+ const char *c_reset = diff_get_color(use_color, DIFF_RESET);
if (rev->loginfo)
show_log(rev, opt->msg_sep);
- dump_quoted_path(dense ? "diff --cc " : "diff --combined ", elem->path);
- printf("index ");
+ dump_quoted_path(dense ? "diff --cc " : "diff --combined ",
+ elem->path, c_meta, c_reset);
+ printf("%sindex ", c_meta);
for (i = 0; i < num_parent; i++) {
abb = find_unique_abbrev(elem->parent[i].sha1,
abbrev);
printf("%s%s", i ? "," : "", abb);
}
abb = find_unique_abbrev(elem->sha1, abbrev);
- printf("..%s\n", abb);
+ printf("..%s%s\n", abb, c_reset);
if (mode_differs) {
int added = !!elem->mode;
@@ -719,10 +736,11 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
DIFF_STATUS_ADDED)
added = 0;
if (added)
- printf("new file mode %06o", elem->mode);
+ printf("%snew file mode %06o",
+ c_meta, elem->mode);
else {
if (!elem->mode)
- printf("deleted file ");
+ printf("%sdeleted file ", c_meta);
printf("mode ");
for (i = 0; i < num_parent; i++) {
printf("%s%06o", i ? "," : "",
@@ -731,11 +749,11 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
if (elem->mode)
printf("..%06o", elem->mode);
}
- putchar('\n');
+ printf("%s\n", c_reset);
}
- dump_quoted_path("--- a/", elem->path);
- dump_quoted_path("+++ b/", elem->path);
- dump_sline(sline, cnt, num_parent);
+ dump_quoted_path("--- a/", elem->path, c_meta, c_reset);
+ dump_quoted_path("+++ b/", elem->path, c_meta, c_reset);
+ dump_sline(sline, cnt, num_parent, opt->color_diff);
}
free(result);
diff --git a/diff.c b/diff.c
index 895c137655..b3b1781a9c 100644
--- a/diff.c
+++ b/diff.c
@@ -1515,10 +1515,8 @@ void diff_setup(struct diff_options *options)
int diff_setup_done(struct diff_options *options)
{
- if ((options->find_copies_harder &&
- options->detect_rename != DIFF_DETECT_COPY) ||
- (0 <= options->rename_limit && !options->detect_rename))
- return -1;
+ if (options->find_copies_harder)
+ options->detect_rename = DIFF_DETECT_COPY;
if (options->output_format & (DIFF_FORMAT_NAME |
DIFF_FORMAT_NAME_STATUS |
diff --git a/git-compat-util.h b/git-compat-util.h
index 3bcf5b13f2..dd92093652 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -139,6 +139,12 @@ static inline ssize_t xwrite(int fd, const void *buf, size_t len)
}
}
+static inline int has_extension(const char *filename, int len, const char *ext)
+{
+ int extlen = strlen(ext);
+ return len > extlen && !memcmp(filename + len - extlen, ext, extlen);
+}
+
/* Sane ctype - no locale, and works with signed chars */
#undef isspace
#undef isdigit
diff --git a/help.c b/help.c
index fb731cc934..7a7f7759e5 100644
--- a/help.c
+++ b/help.c
@@ -140,7 +140,7 @@ static void list_commands(const char *exec_path, const char *pattern)
continue;
entlen = strlen(de->d_name);
- if (4 < entlen && !strcmp(de->d_name + entlen - 4, ".exe"))
+ if (has_extension(de->d_name, entlen, ".exe"))
entlen -= 4;
if (longest < entlen)
diff --git a/http-fetch.c b/http-fetch.c
index 36af3e5b94..6ea39f0589 100644
--- a/http-fetch.c
+++ b/http-fetch.c
@@ -870,7 +870,7 @@ static void process_ls_pack(struct remote_ls_ctx *ls)
if (strlen(ls->dentry_name) == 63 &&
!strncmp(ls->dentry_name, "objects/pack/pack-", 18) &&
- !strncmp(ls->dentry_name+58, ".pack", 5)) {
+ has_extension(ls->dentry_name, 63, ".pack")) {
get_sha1_hex(ls->dentry_name + 18, sha1);
setup_index(ls->repo, sha1);
}
diff --git a/index-pack.c b/index-pack.c
index b39953dc69..a91e39ecd6 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -447,7 +447,7 @@ int main(int argc, char **argv)
usage(index_pack_usage);
if (!index_name) {
int len = strlen(pack_name);
- if (len < 5 || strcmp(pack_name + len - 5, ".pack"))
+ if (!has_extension(pack_name, len, ".pack"))
die("packfile name '%s' does not end with '.pack'",
pack_name);
index_name_buf = xmalloc(len);
diff --git a/local-fetch.c b/local-fetch.c
index 4bf86fbbe2..b6ec170c01 100644
--- a/local-fetch.c
+++ b/local-fetch.c
@@ -43,8 +43,8 @@ static int setup_indices(void)
return -1;
while ((de = readdir(dir)) != NULL) {
int namelen = strlen(de->d_name);
- if (namelen != 50 ||
- strcmp(de->d_name + namelen - 5, ".pack"))
+ if (namelen != 50 ||
+ !has_extension(de->d_name, namelen, ".pack"))
continue;
get_sha1_hex(de->d_name + 5, sha1);
setup_index(sha1);
diff --git a/refs.c b/refs.c
index 02850b6908..b01835f634 100644
--- a/refs.c
+++ b/refs.c
@@ -147,7 +147,7 @@ static int do_for_each_ref(const char *base, int (*fn)(const char *path, const u
namelen = strlen(de->d_name);
if (namelen > 255)
continue;
- if (namelen>5 && !strcmp(de->d_name+namelen-5,".lock"))
+ if (has_extension(de->d_name, namelen, ".lock"))
continue;
memcpy(path + baselen, de->d_name, namelen+1);
if (stat(git_path("%s", path), &st) < 0)
diff --git a/revision.c b/revision.c
index a58257ad80..5a91d06b98 100644
--- a/revision.c
+++ b/revision.c
@@ -936,7 +936,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->diffopt.output_format = DIFF_FORMAT_PATCH;
}
revs->diffopt.abbrev = revs->abbrev;
- diff_setup_done(&revs->diffopt);
+ if (diff_setup_done(&revs->diffopt) < 0)
+ die("diff_setup_done failed");
return left;
}
diff --git a/sha1_file.c b/sha1_file.c
index 43bc2ea0cf..a1bb01ca35 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -590,7 +590,7 @@ static void prepare_packed_git_one(char *objdir, int local)
int namelen = strlen(de->d_name);
struct packed_git *p;
- if (strcmp(de->d_name + namelen - 4, ".idx"))
+ if (!has_extension(de->d_name, namelen, ".idx"))
continue;
/* we have .idx. Is it a file we can map? */
diff --git a/sha1_name.c b/sha1_name.c
index 5fe8e5d4bf..c5a05faeb6 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -193,7 +193,7 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
is_null = !memcmp(sha1, null_sha1, 20);
memcpy(hex, sha1_to_hex(sha1), 40);
- if (len == 40)
+ if (len == 40 || !len)
return hex;
while (len < 40) {
unsigned char sha1_ret[20];
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
new file mode 100755
index 0000000000..d5f2cfb186
--- /dev/null
+++ b/t/t4115-apply-symlink.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Junio C Hamano
+#
+
+test_description='git-apply symlinks and partial files
+
+'
+
+. ./test-lib.sh
+
+test_expect_success setup '
+
+ ln -s path1/path2/path3/path4/path5 link1 &&
+ git add link? &&
+ git commit -m initial &&
+
+ git branch side &&
+
+ rm -f link? &&
+
+ ln -s htap6 link1 &&
+ git update-index link? &&
+ git commit -m second &&
+
+ git diff-tree -p HEAD^ HEAD >patch &&
+ git apply --stat --summary patch
+
+'
+
+test_expect_success 'apply symlink patch' '
+
+ git checkout side &&
+ git apply patch &&
+ git diff-files -p >patched &&
+ diff -u patch patched
+
+'
+
+test_expect_success 'apply --index symlink patch' '
+
+ git checkout -f side &&
+ git apply --index patch &&
+ git diff-index --cached -p HEAD >patched &&
+ diff -u patch patched
+
+'
+
+test_done
diff --git a/verify-pack.c b/verify-pack.c
index c99db9dd79..f440a39678 100644
--- a/verify-pack.c
+++ b/verify-pack.c
@@ -1,43 +1,60 @@
#include "cache.h"
#include "pack.h"
-static int verify_one_pack(char *arg, int verbose)
+static int verify_one_pack(const char *path, int verbose)
{
- int len = strlen(arg);
- struct packed_git *g;
-
- while (1) {
- /* Should name foo.idx, but foo.pack may be named;
- * convert it to foo.idx
- */
- if (!strcmp(arg + len - 5, ".pack")) {
- strcpy(arg + len - 5, ".idx");
- len--;
- }
- /* Should name foo.idx now */
- if ((g = add_packed_git(arg, len, 1)))
- break;
- /* No? did you name just foo? */
+ char arg[PATH_MAX];
+ int len;
+ struct packed_git *pack;
+ int err;
+
+ len = strlcpy(arg, path, PATH_MAX);
+ if (len >= PATH_MAX)
+ return error("name too long: %s", path);
+
+ /*
+ * In addition to "foo.idx" we accept "foo.pack" and "foo";
+ * normalize these forms to "foo.idx" for add_packed_git().
+ */
+ if (has_extension(arg, len, ".pack")) {
+ strcpy(arg + len - 5, ".idx");
+ len--;
+ } else if (!has_extension(arg, len, ".idx")) {
+ if (len + 4 >= PATH_MAX)
+ return error("name too long: %s.idx", arg);
strcpy(arg + len, ".idx");
len += 4;
- if ((g = add_packed_git(arg, len, 1)))
- break;
- return error("packfile %s not found.", arg);
}
- return verify_pack(g, verbose);
+
+ /*
+ * add_packed_git() uses our buffer (containing "foo.idx") to
+ * build the pack filename ("foo.pack"). Make sure it fits.
+ */
+ if (len + 1 >= PATH_MAX) {
+ arg[len - 4] = '\0';
+ return error("name too long: %s.pack", arg);
+ }
+
+ pack = add_packed_git(arg, len, 1);
+ if (!pack)
+ return error("packfile %s not found.", arg);
+
+ err = verify_pack(pack, verbose);
+ free(pack);
+
+ return err;
}
static const char verify_pack_usage[] = "git-verify-pack [-v] <pack>...";
int main(int ac, char **av)
{
- int errs = 0;
+ int err = 0;
int verbose = 0;
int no_more_options = 0;
+ int nothing_done = 1;
while (1 < ac) {
- char path[PATH_MAX];
-
if (!no_more_options && av[1][0] == '-') {
if (!strcmp("-v", av[1]))
verbose = 1;
@@ -47,11 +64,15 @@ int main(int ac, char **av)
usage(verify_pack_usage);
}
else {
- strcpy(path, av[1]);
- if (verify_one_pack(path, verbose))
- errs++;
+ if (verify_one_pack(av[1], verbose))
+ err = 1;
+ nothing_done = 0;
}
ac--; av++;
}
- return !!errs;
+
+ if (nothing_done)
+ usage(verify_pack_usage);
+
+ return err;
}