* maint:
  tutorial: gentler illustration of Alice/Bob workflow using gitk
  pretty=format: respect date format options
  make git-shell paranoid about closed stdin/stdout/stderr
  Document gitk --argscmd flag.
  Fix '--dirstat' with cross-directory renaming
  for-each-ref: Allow a trailing slash in the patterns
This commit is contained in:
Junio C Hamano 2008-08-29 00:16:39 -07:00
Родитель e990501312 53d1589ff6
Коммит 445cac18c0
11 изменённых файлов: 80 добавлений и 12 удалений

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

@ -49,6 +49,13 @@ frequently used options.
the history between two branches (i.e. the HEAD and the MERGE_HEAD)
that modify the conflicted files.
--argscmd=<command>::
Command to be run each time gitk has to determine the list of
<revs> to show. The command is expected to print on its standard
output a list of additional revs to be shown, one per line.
Use this instead of explicitly specifying <revs> if the set of
commits to show may vary between refreshes.
<revs>::
Limit the revisions to show. This can be either a single revision

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

@ -321,10 +321,37 @@ pulling, like this:
------------------------------------------------
alice$ git fetch /home/bob/myrepo master
alice$ git log -p ..FETCH_HEAD
alice$ git log -p HEAD..FETCH_HEAD
------------------------------------------------
This operation is safe even if Alice has uncommitted local changes.
The range notation HEAD..FETCH_HEAD" means "show everything that is reachable
from the FETCH_HEAD but exclude anything that is reachable from HEAD.
Alice already knows everything that leads to her current state (HEAD),
and reviewing what Bob has in his state (FETCH_HEAD) that she has not
seen with this command
If Alice wants to visualize what Bob did since their histories forked
she can issue the following command:
------------------------------------------------
$ gitk HEAD..FETCH_HEAD
------------------------------------------------
This uses the same two-dot range notation we saw earlier with 'git log'.
Alice may want to view what both of them did since they forked.
She can use three-dot form instead of the two-dot form:
------------------------------------------------
$ gitk HEAD...FETCH_HEAD
------------------------------------------------
This means "show everything that is reachable from either one, but
exclude anything that is reachable from both of them".
Please note that these range notation can be used with both gitk
and "git log".
After inspecting what Bob did, if there is nothing urgent, Alice may
decide to continue working without pulling from Bob. If Bob's history

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

@ -103,7 +103,7 @@ The placeholders are:
- '%an': author name
- '%aN': author name (respecting .mailmap)
- '%ae': author email
- '%ad': author date
- '%ad': author date (format respects --date= option)
- '%aD': author date, RFC2822 style
- '%ar': author date, relative
- '%at': author date, UNIX timestamp

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

@ -48,7 +48,7 @@ static void format_subst(const struct commit *commit,
strbuf_add(&fmt, b + 8, c - b - 8);
strbuf_add(buf, src, b - src);
format_commit_message(commit, fmt.buf, buf);
format_commit_message(commit, fmt.buf, buf, DATE_NORMAL);
len -= c + 1 - src;
src = c + 1;
}

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

@ -882,7 +882,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1)
if (!log_tree_commit(&rev, commit)) {
struct strbuf buf = STRBUF_INIT;
format_commit_message(commit, "%h: %s", &buf);
format_commit_message(commit, "%h: %s", &buf, DATE_NORMAL);
printf("%s\n", buf.buf);
strbuf_release(&buf);
}

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

@ -652,7 +652,8 @@ static int grab_single_ref(const char *refname, const unsigned char *sha1, int f
if ((plen <= namelen) &&
!strncmp(refname, p, plen) &&
(refname[plen] == '\0' ||
refname[plen] == '/'))
refname[plen] == '/' ||
p[plen-1] == '/'))
break;
if (!fnmatch(p, refname, FNM_PATHNAME))
break;

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

@ -67,7 +67,8 @@ extern int non_ascii(int);
struct rev_info; /* in revision.h, it circularly uses enum cmit_fmt */
extern void get_commit_format(const char *arg, struct rev_info *);
extern void format_commit_message(const struct commit *commit,
const void *format, struct strbuf *sb);
const void *format, struct strbuf *sb,
enum date_mode dmode);
extern void pretty_print_commit(enum cmit_fmt fmt, const struct commit*,
struct strbuf *,
int abbrev, const char *subject,

8
diff.c
Просмотреть файл

@ -1060,6 +1060,13 @@ static long gather_dirstat(FILE *file, struct dirstat_dir *dir, unsigned long ch
return this_dir;
}
static int dirstat_compare(const void *_a, const void *_b)
{
const struct dirstat_file *a = _a;
const struct dirstat_file *b = _b;
return strcmp(a->name, b->name);
}
static void show_dirstat(struct diff_options *options)
{
int i;
@ -1119,6 +1126,7 @@ static void show_dirstat(struct diff_options *options)
return;
/* Show all directories with more than x% of the changes */
qsort(dir.files, dir.nr, sizeof(dir.files[0]), dirstat_compare);
gather_dirstat(options->file, &dir, changed, "", 0);
}

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

@ -310,7 +310,7 @@ static int mailmap_name(struct strbuf *sb, const char *email)
}
static size_t format_person_part(struct strbuf *sb, char part,
const char *msg, int len)
const char *msg, int len, enum date_mode dmode)
{
/* currently all placeholders have same length */
const int placeholder_len = 2;
@ -377,7 +377,7 @@ static size_t format_person_part(struct strbuf *sb, char part,
switch (part) {
case 'd': /* date */
strbuf_addstr(sb, show_date(date, tz, DATE_NORMAL));
strbuf_addstr(sb, show_date(date, tz, dmode));
return placeholder_len;
case 'D': /* date, RFC2822 style */
strbuf_addstr(sb, show_date(date, tz, DATE_RFC2822));
@ -409,6 +409,7 @@ struct chunk {
struct format_commit_context {
const struct commit *commit;
enum date_mode dmode;
/* These offsets are relative to the start of the commit message. */
int commit_header_parsed;
@ -584,10 +585,12 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
return 1;
case 'a': /* author ... */
return format_person_part(sb, placeholder[1],
msg + c->author.off, c->author.len);
msg + c->author.off, c->author.len,
c->dmode);
case 'c': /* committer ... */
return format_person_part(sb, placeholder[1],
msg + c->committer.off, c->committer.len);
msg + c->committer.off, c->committer.len,
c->dmode);
case 'e': /* encoding */
strbuf_add(sb, msg + c->encoding.off, c->encoding.len);
return 1;
@ -599,12 +602,14 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
}
void format_commit_message(const struct commit *commit,
const void *format, struct strbuf *sb)
const void *format, struct strbuf *sb,
enum date_mode dmode)
{
struct format_commit_context context;
memset(&context, 0, sizeof(context));
context.commit = commit;
context.dmode = dmode;
strbuf_expand(sb, format, format_commit_item, &context);
}
@ -770,7 +775,7 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit,
const char *encoding;
if (fmt == CMIT_FMT_USERFORMAT) {
format_commit_message(commit, user_format, sb);
format_commit_message(commit, user_format, sb, dmode);
return;
}

13
shell.c
Просмотреть файл

@ -48,6 +48,19 @@ int main(int argc, char **argv)
{
char *prog;
struct commands *cmd;
int devnull_fd;
/*
* Always open file descriptors 0/1/2 to avoid clobbering files
* in die(). It also avoids not messing up when the pipes are
* dup'ed onto stdin/stdout/stderr in the child processes we spawn.
*/
devnull_fd = open("/dev/null", O_RDWR);
while (devnull_fd >= 0 && devnull_fd <= 2)
devnull_fd = dup(devnull_fd);
if (devnull_fd == -1)
die("opening /dev/null failed (%s)", strerror(errno));
close (devnull_fd);
/*
* Special hack to pretend to be a CVS server

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

@ -139,6 +139,12 @@ commit 131a310eb913d107dd3c09a65d1651175898735d
commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
EOF
test_expect_success '%ad respects --date=' '
echo 2005-04-07 >expect.ad-short &&
git log -1 --date=short --pretty=tformat:%ad >output.ad-short master &&
test_cmp expect.ad-short output.ad-short
'
test_expect_success 'empty email' '
test_tick &&
C=$(GIT_AUTHOR_EMAIL= git commit-tree HEAD^{tree} </dev/null) &&