Merge branch 'master' into mk/rename

* master:
  git-verify-pack: no need to count errors
  git-verify-pack: buffer overrun paranoia
  git-verify-pack: free pack after use and a cleanup
  git-verify-pack: get rid of while loop
  git-verify-pack: insist on .idx extension
  git-verify-pack: more careful path handling
  git-verify-pack: show usage when no pack was specified
  Add has_extension()
  builtin-apply: remove unused increment
  Fix git-diff A...B
  combine-diff: use color
  git-apply: applying a patch to make a symlink shorter.
  allow diff.renamelimit to be set regardless of -M/-C
  make --find-copies-harder imply -C
  find_unique_abbrev() with len=0 should not abbreviate
  check return value from diff_setup_done()
  Fix tutorial-2.html
  Documentation: git-status takes the same options as git-commit
  Update git-init-db(1) and documentation of core.sharedRepository
This commit is contained in:
Junio C Hamano 2006-08-10 14:17:49 -07:00
Родитель 102cb08521 0eaf22f4c4
Коммит 44e1d764d0
19 изменённых файлов: 209 добавлений и 78 удалений

Просмотреть файл

@ -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

Просмотреть файл

@ -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.
--
--template=<template_directory>::
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.

Просмотреть файл

@ -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
------

Просмотреть файл

@ -244,6 +244,7 @@ $ git ls-files --stage
$ git cat-file -t 513feba2
blob
$ git cat-file blob 513feba2
hello world!
hello world, again
------------------------------------------------

Просмотреть файл

@ -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)

Просмотреть файл

@ -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

Просмотреть файл

@ -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);

6
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 |

Просмотреть файл

@ -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

2
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)

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -44,7 +44,7 @@ static int setup_indices(void)
while ((de = readdir(dir)) != NULL) {
int namelen = strlen(de->d_name);
if (namelen != 50 ||
strcmp(de->d_name + namelen - 5, ".pack"))
!has_extension(de->d_name, namelen, ".pack"))
continue;
get_sha1_hex(de->d_name + 5, sha1);
setup_index(sha1);

2
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)

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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? */

Просмотреть файл

@ -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];

49
t/t4115-apply-symlink.sh Executable file
Просмотреть файл

@ -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

Просмотреть файл

@ -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;
char arg[PATH_MAX];
int len;
struct packed_git *pack;
int err;
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? */
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;
}