* [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
@ 2005-06-07 9:15 Jon Seymour
2005-06-07 9:30 ` Jon Seymour
2005-06-07 9:49 ` Petr Baudis
0 siblings, 2 replies; 10+ messages in thread
From: Jon Seymour @ 2005-06-07 9:15 UTC (permalink / raw)
To: git; +Cc: torvalds, jon.seymour
[PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
This patch is a complete replacement for:
[PATCH] Add support for --wrt flag to git-rev-list
This patch adds support for --wrt-author, --exclude-author and --author switches
to git-rev-list.
When --wrt-author is specified, --merge-order is implied but
the linearisation of non-linear epochs is adjusted so that branches
contributed to by the author sort after branches contributed to by
others. This has the effect of presenting a linear history of changes as seen
by the author's own workspace.
For example, given this commit history:
a4 ---
| \ \
| b4 |
|/ | |
a3 | |
| | |
a2 | |
| | c3
| | |
| | c2
| b3 |
| | /|
| b2 |
| | c1
| | /
| b1 <-- commit authored by author@domain
a1 |
| |
a0 |
| /
root
--merge-order alone would sort it as follows:
= a4
| c3
| c2
| c1
^ b4
| b3
| b2
| b1
^ a3
| a2
| a1
| a0
= root
however, with --wrt-author --author=author@domain, git-rev-list sorts as follows:
= a4
| c3
| c2
| c1
^ b4
| a3
| a2
| a1
| a0
^ b3
| b2
| b1
= root
If --exclude-author is specified, then git-rev-list behaves as if a
^argument had been added for each commit authored by the author.
The --exclude-author option allows an author to see a brief summary of
changes since they last made a contribution to the commit graph. For example:
git-rev-list --exclude-author --pretty HEAD
To configure which author git-rev-list uses when processing the --wrt-author
and --exclude-author switches, use the --author=author@domain option. If this
option is not specified, git-rev-list uses GIT_AUTHOR_EMAIL or a value
derived from the local user, host and domain names (per git-commit-tree's algorithm)
To support this change, some additional functions were added to commit.c to allow
the extraction of author from the commit header.
Also, --show-breaks, like --wrt-author now implies --merge-order rather than requires it.
This change also updates Documentation/git-rev-list.txt to include documentation for
--wrt-author and other git-rev-list options not currently documented.
A test case has been included in t/t6000-rev-list.sh to verify this change works as
expected.
Use of --wrt-author implies a small overhead (linear with respect to nodes printed) compared with --merge-order.
This change extracts real email id formatting functions from commit-tree.c into user.c and user.h.
NOTE TO REVIEWERS: please pay special attention to get_real_identity()
which was extracted from commit-tree.c and placed into user.c. It was essentially
a cut and paste, but since this has the potential to affect the operation of git-commit-tree,
it would be worth being very careful about checking this change.
Signed-off-by: Jon Seymour <jon.seymour@gmail.com>
Diverged from ed37b5b2b94398f3ab8312dfdf23cfd25549e3ec by Linus Torvalds <torvalds@ppc970.osdl.org>
---
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -9,13 +9,25 @@ git-rev-list - Lists commit objects in r
SYNOPSIS
--------
-'git-rev-list' [ *--max-count*=number ] [ *--max-age*=timestamp ] [ *--min-age*=timestamp ] [ *--merge-order* [ *--show-breaks* ] ] <commit>
+'git-rev-list' [ *--max-count*=number ] [ *--max-age*=timestamp ] [ *--min-age*=timestamp ] [ *--pretty* ] [ *--parents* ] [ *--header* ] [ *--merge-order* ] [ *--show-breaks* ] [ *--wrt-author* ] [ *--exclude-author* ] [ *--author=author@domain* ] <head-to-include> <head-to-include> ...
+^<base-to-exclude>
+^<base-to-exclude> ...
DESCRIPTION
-----------
-Lists commit objects in reverse chronological order starting at the
-given commit, taking ancestry relationship into account. This is
-useful to produce human-readable log output.
+
+Lists commit objects in reverse chronological order starting at the commits specified by head-to-include values,
+taking ancestry relationship into account. git-rev-list will not print any commits that are reachable
+by any of the base-to-exclude values.
+
+If *--pretty* is specified, git-rev-list prints a short summary of each commit on stdout. This can be usefully
+parsed by git-shortlog to produce a short log of changes.
+
+If *--parents* is specified, git-rev-list prints a space separated list of parents on the same line as the
+commit identifier.
+
+If *--header* is specified, git-rev-list prints to stdout, on line after the identifier of each commit,
+the contents of the commit's header followed by a trailing NUL.
If *--merge-order* is specified, the commit history is decomposed into a unique sequence of minimal, non-linear
epochs and maximal, linear epochs. Non-linear epochs are then linearised by sorting them into merge order, which
@@ -42,17 +54,30 @@ Commits marked with (=) represent the bo
Commits marked with (|) are direct parents of commits immediately preceding the marked commit in the list.
Commits marked with (^) are not parents of the immediately preceding commit. These "breaks" represent necessary discontinuities implied by trying to represent an arbtirary DAG in a linear form.
-*--show-breaks* is only valid if *--merge-order* is also specified.
+The *--author* option is used to specify the author used by the *--wrt-author* and *--exclude-author* switches. If
+an *--author* option is not specified, the author used is derived from GIT_AUTHOR_EMAIL or, ultimately,
+from the local user, host and domain names as per the logic used by git-commit-tree.
+
+If *--wrt=author* is specified, then git-rev-list sorts commits so that contemporaneously
+developed commits appear to occur after (that is, sort before) any commits authored by the
+author specified by *--author*. This reflects the order in which that author
+sees contemporaneously developed commits appear in her own workspace.
+
+If *--exclude-author* is specified, then any commit authored by the author is marked as uninteresting as if it
+had been specified with ^ on the command line. This option restricts git-rev-list's to just the changes since
+the author contributed a change.
+
+Use of *--show-breaks*, *--exclude-author* or *--wrt-author* implies *--merge-order*.
Author
------
Written by Linus Torvalds <torvalds@osdl.org>
-Original *--merge-order* logic by Jon Seymour <jon.seymour@gmail.com>
+Original *--merge-order*, *--wrt-author* and *--exclude-author* logic by Jon Seymour <jon.seymour@gmail.com>
Documentation
--------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
+Documentation by David Greaves, Junio C Hamano, Jon Seymour and the git-list <git@vger.kernel.org>.
GIT
---
diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -41,9 +41,9 @@ install: $(PROG) $(SCRIPTS)
LIB_OBJS=read-cache.o sha1_file.o usage.o object.o commit.o tree.o blob.o \
tag.o delta.o date.o index.o diff-delta.o patch-delta.o entry.o \
- epoch.o refs.o
+ epoch.o refs.o user.o
LIB_FILE=libgit.a
-LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h
+LIB_H=cache.h object.h blob.h tree.h commit.h tag.h delta.h epoch.h user.h
LIB_H += strbuf.h
LIB_OBJS += strbuf.o
@@ -138,6 +138,7 @@ diffcore-pickaxe.o : $(LIB_H) diffcore.h
diffcore-break.o : $(LIB_H) diffcore.h
diffcore-order.o : $(LIB_H) diffcore.h
epoch.o: $(LIB_H)
+user.o: $(LIB_H)
test: all
$(MAKE) -C t/ all
diff --git a/commit-tree.c b/commit-tree.c
--- a/commit-tree.c
+++ b/commit-tree.c
@@ -4,10 +4,11 @@
* Copyright (C) Linus Torvalds, 2005
*/
#include "cache.h"
+#include "user.h"
-#include <pwd.h>
#include <time.h>
#include <ctype.h>
+#include <pwd.h>
#define BLOCKING (1ul << 14)
@@ -100,17 +101,16 @@ static char *commit_tree_usage = "git-co
int main(int argc, char **argv)
{
- int i, len;
+ int i;
int parents = 0;
unsigned char tree_sha1[20];
unsigned char parent_sha1[MAXPARENT][20];
unsigned char commit_sha1[20];
char *gecos, *realgecos, *commitgecos;
- char *email, *commitemail, realemail[1000];
+ char *email, *commitemail, *realemail;
char date[50], realdate[50];
char *audate, *cmdate;
char comment[1000];
- struct passwd *pw;
char *buffer;
unsigned int size;
@@ -128,18 +128,8 @@ int main(int argc, char **argv)
}
if (!parents)
fprintf(stderr, "Committing initial tree %s\n", argv[1]);
- pw = getpwuid(getuid());
- if (!pw)
- die("You don't exist. Go away!");
- realgecos = pw->pw_gecos;
- len = strlen(pw->pw_name);
- memcpy(realemail, pw->pw_name, len);
- realemail[len] = '@';
- gethostname(realemail+len+1, sizeof(realemail)-len-1);
- if (!strchr(realemail+len+1, '.')) {
- strcat(realemail, ".");
- getdomainname(realemail+strlen(realemail), sizeof(realemail)-strlen(realemail)-1);
- }
+
+ get_real_identity(&realemail, &realgecos);
datestamp(realdate, sizeof(realdate));
strcpy(date, realdate);
diff --git a/commit.c b/commit.c
--- a/commit.c
+++ b/commit.c
@@ -302,3 +302,65 @@ int count_parents(struct commit * commit
return count;
}
+int copy_commit_header(struct commit * commit, char * header, int index, char * buffer, int len)
+{
+ char * p = commit->buffer;
+
+ while (*p) {
+
+ char * q = header;
+ if (*p == '\n') {
+ break;
+ }
+
+ int matched;
+
+ for (matched = 1; *p != ' ' && *p != '\n'; p++, q++) {
+ matched = matched & (*q==*p);
+ }
+
+ if (matched && index) {
+ // if we matched but we haven't seen the index'th element yet,
+ // just decrement the index then pretend we didn't match
+ index--;
+ matched = 0;
+ }
+
+ if (!matched) {
+
+ // skip to start of next header line
+
+ for (;*p!='\n';p++)
+ ;
+ p++;
+
+ } else {
+
+ int count = 0; // number of characters in value
+
+ if (*p == ' ') {
+ p++;
+
+ for (count = 0; *p != '\n'; p++, count++, len--) {
+ if (len > 0) {
+ *buffer++=*p;
+ }
+ }
+
+ }
+
+ if (len > 0) {
+ *buffer = 0;
+ }
+
+ return (len > 0) ? count+1 : -(count+1);
+
+ }
+ }
+ return 0;
+}
+
+int copy_author(struct commit * commit, char * buffer, int len)
+{
+ return copy_commit_header(commit, "author", 0, buffer, len);
+}
diff --git a/commit.h b/commit.h
--- a/commit.h
+++ b/commit.h
@@ -53,4 +53,17 @@ struct commit *pop_most_recent_commit(st
struct commit *pop_commit(struct commit_list **stack);
int count_parents(struct commit * commit);
+
+//
+// Copies the value of the (index+1)'th commit header matching the name specified
+// into the buffer supplied and append a trailing NUL.
+//
+// Returns n<0 if the buffer was too short (-n is the required length)
+// Returns 0 if the header doesn't exist.
+// Returns n>0 where n is the length of the copied zero-terminated value, including the terminating zero.
+//
+int copy_commit_header(struct commit * commit, char * header, int index, char * buffer, int len);
+
+// Copies the commit's author value into the buffer supplied. Return values as per copy_commit_header.
+int copy_author(struct commit * commit, char * buffer, int len);
#endif /* COMMIT_H */
diff --git a/epoch.c b/epoch.c
--- a/epoch.c
+++ b/epoch.c
@@ -450,11 +450,15 @@ static void mark_ancestors_uninteresting
// Sorts the nodes of the first epoch of the epoch sequence of the epoch headed at head
// into merge order.
//
-static void sort_first_epoch(struct commit *head, struct commit_list **stack)
+static void sort_first_epoch(struct commit *head, struct commit_list **stack, marker_func marker)
{
struct commit_list *parents;
struct commit_list *reversed_parents = NULL;
+ if (marker) {
+ (*marker)(head);
+ }
+
head->object.flags |= VISITED;
//
@@ -464,17 +468,21 @@ static void sort_first_epoch(struct comm
// so we need to reverse this list to output the oldest (or most "local") commits last.
//
- for (parents = head->parents; parents; parents = parents->next)
- commit_list_insert(parents->item, &reversed_parents);
-
- //
- // todo: by sorting the parents in a different order, we can alter the
- // merge order to show contemporaneous changes in parallel branches
- // occurring after "local" changes. This is useful for a developer
- // when a developer wants to see all changes that were incorporated
- // into the same merge as her own changes occur after her own
- // changes.
- //
+ if (!head->object.util) {
+
+ for (parents = head->parents; parents; parents = parents->next)
+ commit_list_insert(parents->item, &reversed_parents);
+
+ } else {
+
+ // reverse the locally sorted parents and reset utility pointer to NULL
+
+ parents = (struct commit_list *)head->object.util;
+ head->object.util = NULL;
+ while (parents) {
+ commit_list_insert(pop_commit(&parents), &reversed_parents);
+ }
+ }
while (reversed_parents) {
@@ -502,7 +510,7 @@ static void sort_first_epoch(struct comm
} else {
- sort_first_epoch(parent, stack);
+ sort_first_epoch(parent, stack, marker);
if (reversed_parents) {
//
@@ -555,13 +563,82 @@ static int emit_stack(struct commit_list
}
//
+// Sort a list of commits in local last order. A commit is "local" if any of its ancestors (except the base)
+// causes (*local_test)() to return a non-zero value.
+//
+// The sorted list is returned in *sorted. A side effect of this function is to set each object.util
+// pointer to a list of parents sorted in local_last order.
+//
+// Does nothing except set *sorted to NULL if either list or local_test are NULL.
+//
+static void sort_list_in_local_last_order(struct commit_list * list, local_test_func local_test, struct commit_list ** sorted)
+{
+ if (!list || !local_test) {
+ *sorted = NULL;
+ return;
+ }
+
+ struct commit_list * next;
+
+ for ( next = list ; next; next = next->next) {
+
+ struct commit * item = next->item;
+
+ if (item->object.flags & BOUNDARY || item->object.util) {
+ // we have already visited this item or we have
+ // reached the boundary.
+ continue;
+ }
+
+ if ((*local_test)(item)) {
+ item->object.flags |= LOCAL;
+ }
+
+ sort_list_in_local_last_order(item->parents, local_test, (struct commit_list **)&item->object.util);
+
+ struct commit_list * sorted_parents = (struct commit_list *)&item->object.util;
+
+ if (sorted_parents && (sorted_parents->item->object.flags & LOCAL)) {
+ item->object.flags |= LOCAL;
+ }
+ }
+
+ //
+ // Iterate over the original list and generate two lists - a list of the
+ // non-local parents and list of local parents. Then splice the list
+ // of local parents onto the end of the non-local parents to form
+ // a new list.
+ //
+
+ struct commit_list * non_local = NULL;
+ struct commit_list * local = NULL;
+ struct commit_list **p = &local;
+ struct commit_list **q = &non_local;
+
+ for (next = list; next; next = next->next) {
+
+ if (next->item->object.flags & LOCAL) {
+ *p = commit_list_insert(next->item, p);
+ p = &(*p)->next;
+ } else {
+ *q = commit_list_insert(next->item, q);
+ q = &(*q)->next;
+ }
+ }
+
+ *q = local;
+ *sorted = non_local;
+
+}
+
+//
// Sorts an arbitrary epoch into merge order by sorting each epoch
// of its epoch sequence into order.
//
// Note: this algorithm currently leaves traces of its execution in the
// object flags of nodes it discovers. This should probably be fixed.
//
-static int sort_in_merge_order(struct commit *head_of_epoch, emitter_func emitter)
+static int sort_in_merge_order(struct commit *head_of_epoch, emitter_func emitter, local_test_func local_test, marker_func marker)
{
struct commit *next = head_of_epoch;
int ret = 0;
@@ -586,6 +663,10 @@ static int sort_in_merge_order(struct co
while (HAS_EXACTLY_ONE_PARENT(next)
&& (action != STOP)
&& !ret) {
+
+ if (marker) {
+ (*marker)(next);
+ }
if (next->object.flags & UNINTERESTING) {
action = STOP;
@@ -602,7 +683,10 @@ static int sort_in_merge_order(struct co
} else {
struct commit_list *stack = NULL;
- sort_first_epoch(next, &stack);
+
+ sort_list_in_local_last_order(next->parents, local_test, (struct commit_list **)&next->object.util);
+
+ sort_first_epoch(next, &stack, marker);
action = emit_stack(&stack, emitter);
next = base;
@@ -623,7 +707,7 @@ static int sort_in_merge_order(struct co
// subgraph using the sort_first_epoch algorithm. Once we have reached the base
// we can continue sorting using sort_in_merge_order.
//
-int sort_list_in_merge_order(struct commit_list *list, emitter_func emitter)
+int sort_list_in_merge_order(struct commit_list *list, emitter_func emitter, local_test_func local_test, marker_func marker)
{
struct commit_list *stack = NULL;
struct commit *base;
@@ -631,7 +715,8 @@ int sort_list_in_merge_order(struct comm
int ret = 0;
int action = CONTINUE;
- struct commit_list *reversed = NULL;
+ struct commit_list *filtered = NULL;
+ struct commit_list **p = &filtered;
for (; list; list = list->next) {
@@ -642,37 +727,50 @@ int sort_list_in_merge_order(struct comm
fprintf(stderr, "%s: duplicate commit %s ignored\n", __FUNCTION__, sha1_to_hex(next->object.sha1));
} else {
next->object.flags |= DUPCHECK;
- commit_list_insert(list->item, &reversed);
+ *p = commit_list_insert(list->item, p);
+ p = &(*p)->next;
}
}
}
- if (!reversed->next) {
+ if (!filtered->next) {
// if there is only one element in the list, we can sort it using
// sort_in_merge_order.
- base = reversed->item;
+ base = filtered->item;
} else {
// otherwise, we search for the base of the list
- if ((ret = find_base_for_list(reversed, &base)))
+ if ((ret = find_base_for_list(filtered, &base)))
return ret;
if (base) {
base->object.flags |= BOUNDARY;
}
-
+
+ struct commit_list * sorted;
+
+ sort_list_in_local_last_order(filtered, local_test, &sorted);
+
+ if (!sorted) {
+ sorted = filtered;
+ }
+
+ struct commit_list * reversed = NULL;
+ while (sorted)
+ commit_list_insert(pop_commit(&sorted), &reversed);
+
while (reversed) {
- sort_first_epoch(pop_commit(&reversed), &stack);
+ sort_first_epoch(pop_commit(&reversed), &stack, marker);
if (reversed) {
//
// if we have more commits to push, then the
- // first push for the next parent may (or may not)
+ // first push for the next commit may (or may not)
// represent a discontinuity with respect to the
- // parent currently on the top of the stack.
+ // commit currently on the top of the stack.
//
// mark it for checking here, and check it
// with the next push...see sort_first_epoch for
@@ -686,8 +784,9 @@ int sort_list_in_merge_order(struct comm
}
if (base && (action != STOP)) {
- ret = sort_in_merge_order(base, emitter);
+ ret = sort_in_merge_order(base, emitter, local_test, marker);
}
return ret;
}
+
diff --git a/epoch.h b/epoch.h
--- a/epoch.h
+++ b/epoch.h
@@ -8,13 +8,19 @@
#define DO 2
typedef int (*emitter_func) (struct commit *);
-int sort_list_in_merge_order(struct commit_list *list, emitter_func emitter);
+// functions of this type return non-zero if the commit is "local" by some private assessment of
+// what it is for a commit to be local.
+typedef int (*local_test_func) (struct commit *);
+typedef void (*marker_func) (struct commit *);
+
+extern int sort_list_in_merge_order(struct commit_list *list, emitter_func emitter, local_test_func local_test, marker_func marker);
#define UNINTERESTING (1u<<2)
#define BOUNDARY (1u<<3)
#define VISITED (1u<<4)
#define DISCONTINUITY (1u<<5)
#define DUPCHECK (1u<<6)
+#define LOCAL (1u<<7)
#endif /* EPOCH_H */
diff --git a/rev-list.c b/rev-list.c
--- a/rev-list.c
+++ b/rev-list.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "commit.h"
#include "epoch.h"
+#include "user.h"
#define SEEN (1u << 0)
#define INTERESTING (1u << 1)
@@ -11,8 +12,13 @@ static const char rev_list_usage[] =
" --max-age=epoch\n"
" --min-age=epoch\n"
" --header\n"
+ " --parents\n"
" --pretty\n"
- " --merge-order [ --show-breaks ]";
+ " --merge-order\n"
+ " --wrt-author\n"
+ " --exclude-author\n"
+ " --author author@domain\n"
+ " --show-breaks ]";
static int verbose_header = 0;
static int show_parents = 0;
@@ -24,6 +30,9 @@ static int max_count = -1;
static enum cmit_fmt commit_format = CMIT_FMT_RAW;
static int merge_order = 0;
static int show_breaks = 0;
+static char * local_author = NULL;
+static int exclude_author = 0;
+static int wrt_author = 0;
static void show_commit(struct commit *commit)
{
@@ -147,6 +156,23 @@ static enum cmit_fmt get_commit_format(c
usage(rev_list_usage);
}
+static int is_local_author(struct commit * commit)
+{
+ static char author[16384];
+ if (copy_author(commit, author, sizeof(author)) > 0) {
+ if (strstr(author, local_author)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void mark_authors_own_uninteresting(struct commit * commit)
+{
+ if (is_local_author(commit)) {
+ commit->object.flags |= UNINTERESTING;
+ }
+}
int main(int argc, char **argv)
{
@@ -192,6 +218,19 @@ int main(int argc, char **argv)
}
if (!strncmp(arg, "--show-breaks", 13)) {
show_breaks = 1;
+ merge_order = 1;
+ continue;
+ }
+ if (!strncmp(arg, "--author=", 9)) {
+ local_author=strdup(&arg[9]);
+ continue;
+ }
+ if (!strncmp(arg, "--wrt-author", 6)) {
+ wrt_author = 1;
+ continue;
+ }
+ if (!strncmp(arg, "--exclude-author", 16)) {
+ exclude_author = 1;
continue;
}
@@ -201,7 +240,7 @@ int main(int argc, char **argv)
arg++;
limited = 1;
}
- if (get_sha1(arg, sha1) || (show_breaks && !merge_order))
+ if (get_sha1(arg, sha1))
usage(rev_list_usage);
commit = lookup_commit_reference(sha1);
if (!commit || parse_commit(commit) < 0)
@@ -213,6 +252,8 @@ int main(int argc, char **argv)
if (!list)
usage(rev_list_usage);
+ merge_order = merge_order || wrt_author || exclude_author || show_breaks;
+
if (!merge_order) {
if (limited)
@@ -220,11 +261,31 @@ int main(int argc, char **argv)
show_commit_list(list);
} else {
+
+ if ((exclude_author|wrt_author) && !local_author) {
+ local_author = strdup(gitenv("GIT_AUTHOR_EMAIL")) ? : NULL;
+ if (!local_author) {
+ get_real_identity(&local_author, NULL);
+ }
+ }
- if (sort_list_in_merge_order(list, &process_commit)) {
- die("merge order sort failed\n");
+ if (local_author) {
+ // add delimiters to improve accuracy of match
+ char * tmp=xmalloc(strlen(local_author)+3);
+ sprintf(tmp, "<%s>", local_author);
+ free(local_author);
+ local_author = tmp;
+ }
+
+ if (sort_list_in_merge_order(
+ list,
+ &process_commit,
+ local_author ? &is_local_author : NULL,
+ exclude_author ? &mark_authors_own_uninteresting : NULL)
+ ) {
+ die("merge order sort failed\n");
}
-
+
}
return 0;
diff --git a/user.c b/user.c
new file mode 100644
--- /dev/null
+++ b/user.c
@@ -0,0 +1,32 @@
+#include "cache.h"
+#include "user.h"
+#include <string.h>
+#include <pwd.h>
+
+void get_real_identity(char **email, char **gecos)
+{
+ static char buffer[1000];
+ struct passwd *pw;
+ int len;
+
+ pw = getpwuid(getuid());
+ if (!pw)
+ die("You don't exist. Go away!");
+
+ len = strlen(pw->pw_name);
+ memcpy(buffer, pw->pw_name, len);
+ buffer[len] = '@';
+ gethostname(buffer + len + 1, sizeof(buffer) - len - 1);
+ if (!strchr(buffer + len + 1, '.')) {
+ strcat(buffer, ".");
+ getdomainname(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer) - 1);
+ }
+
+ if (gecos) {
+ *gecos = strdup(pw->pw_gecos);
+ }
+
+ if (email) {
+ *email = strdup(buffer);
+ }
+}
diff --git a/user.h b/user.h
new file mode 100644
--- /dev/null
+++ b/user.h
@@ -0,0 +1,8 @@
+#ifndef USER_H
+#define USER_H
+//
+// Allocates two new strings to contain the real email and
+// name of the current user.
+//
+extern void get_real_identity(char **email, char **gecos);
+#endif
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
2005-06-07 9:15 [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list Jon Seymour
@ 2005-06-07 9:30 ` Jon Seymour
2005-06-07 9:49 ` Petr Baudis
1 sibling, 0 replies; 10+ messages in thread
From: Jon Seymour @ 2005-06-07 9:30 UTC (permalink / raw)
To: git; +Cc: torvalds, jon.seymour
A small update to the patch which corrects a couple of documentation typos and a
slight correction to git-rev-list options processing has been posted
here. The update has been tested with a complete apply+build from the
base commit.
http://blackcubes.dyndns.org/epoch/wrt-patch.patch
Regards,
jon.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
2005-06-07 9:15 [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list Jon Seymour
2005-06-07 9:30 ` Jon Seymour
@ 2005-06-07 9:49 ` Petr Baudis
[not found] ` <2cfc403205060702594da21fb1@mail.gmail.com>
1 sibling, 1 reply; 10+ messages in thread
From: Petr Baudis @ 2005-06-07 9:49 UTC (permalink / raw)
To: Jon Seymour; +Cc: git, torvalds
Dear diary, on Tue, Jun 07, 2005 at 11:15:23AM CEST, I got a letter
where Jon Seymour <jon.seymour@gmail.com> told me that...
> [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
>
> This patch is a complete replacement for:
> [PATCH] Add support for --wrt flag to git-rev-list
>
> This patch adds support for --wrt-author, --exclude-author and --author switches
> to git-rev-list.
I'd prefer just --wrt-author and --exclude-author to take an argument on
their own.
(Note that I don't endorse this patch and the --wrt-author behaviour in
particular seems strange. I don't have enough time to comment on it
sensibly now, though. I'm just focusing on style here since I'd like to
still be able to read git's source code few weeks from now on.)
> Diverged from ed37b5b2b94398f3ab8312dfdf23cfd25549e3ec by Linus Torvalds <torvalds@ppc970.osdl.org>
> ---
> diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
> --- a/Documentation/git-rev-list.txt
> +++ b/Documentation/git-rev-list.txt
> @@ -9,13 +9,25 @@ git-rev-list - Lists commit objects in r
>
> SYNOPSIS
> --------
> -'git-rev-list' [ *--max-count*=number ] [ *--max-age*=timestamp ] [ *--min-age*=timestamp ] [ *--merge-order* [ *--show-breaks* ] ] <commit>
> +'git-rev-list' [ *--max-count*=number ] [ *--max-age*=timestamp ] [ *--min-age*=timestamp ] [ *--pretty* ] [ *--parents* ] [ *--header* ] [ *--merge-order* ] [ *--show-breaks* ] [ *--wrt-author* ] [ *--exclude-author* ] [ *--author=author@domain* ] <head-to-include> <head-to-include> ...
> +^<base-to-exclude>
> +^<base-to-exclude> ...
>
> DESCRIPTION
> -----------
> -Lists commit objects in reverse chronological order starting at the
> -given commit, taking ancestry relationship into account. This is
> -useful to produce human-readable log output.
> +
> +Lists commit objects in reverse chronological order starting at the commits specified by head-to-include values,
> +taking ancestry relationship into account. git-rev-list will not print any commits that are reachable
> +by any of the base-to-exclude values.
Could you please break your lines somewhere before the 80th column?
This applies to the code too (actually it applies more to the code,
comments in particular).
> diff --git a/commit-tree.c b/commit-tree.c
> --- a/commit-tree.c
> +++ b/commit-tree.c
> @@ -128,18 +128,8 @@ int main(int argc, char **argv)
> }
> if (!parents)
> fprintf(stderr, "Committing initial tree %s\n", argv[1]);
> - pw = getpwuid(getuid());
> - if (!pw)
> - die("You don't exist. Go away!");
> - realgecos = pw->pw_gecos;
> - len = strlen(pw->pw_name);
> - memcpy(realemail, pw->pw_name, len);
> - realemail[len] = '@';
> - gethostname(realemail+len+1, sizeof(realemail)-len-1);
> - if (!strchr(realemail+len+1, '.')) {
> - strcat(realemail, ".");
> - getdomainname(realemail+strlen(realemail), sizeof(realemail)-strlen(realemail)-1);
> - }
> +
> + get_real_identity(&realemail, &realgecos);
Whitespace police emergency.
>
> datestamp(realdate, sizeof(realdate));
> strcpy(date, realdate);
> diff --git a/commit.c b/commit.c
> --- a/commit.c
> +++ b/commit.c
> @@ -302,3 +302,65 @@ int count_parents(struct commit * commit
> return count;
> }
>
> +int copy_commit_header(struct commit * commit, char * header, int index, char * buffer, int len)
> +{
> + char * p = commit->buffer;
> +
> + while (*p) {
> +
> + char * q = header;
> + if (*p == '\n') {
> + break;
> + }
> +
> + int matched;
> +
> + for (matched = 1; *p != ' ' && *p != '\n'; p++, q++) {
> + matched = matched & (*q==*p);
> + }
> +
> + if (matched && index) {
> + // if we matched but we haven't seen the index'th element yet,
> + // just decrement the index then pretend we didn't match
> + index--;
> + matched = 0;
> + }
> +
> + if (!matched) {
> +
> + // skip to start of next header line
> +
> + for (;*p!='\n';p++)
> + ;
> + p++;
> +
> + } else {
> +
> + int count = 0; // number of characters in value
> +
> + if (*p == ' ') {
> + p++;
> +
> + for (count = 0; *p != '\n'; p++, count++, len--) {
> + if (len > 0) {
> + *buffer++=*p;
> + }
> + }
> +
> + }
> +
> + if (len > 0) {
> + *buffer = 0;
> + }
> +
> + return (len > 0) ? count+1 : -(count+1);
> +
> + }
> + }
> + return 0;
> +}
Another style comment - I think the code is way too diffused, suffering
by hyperemptylineosis, which subsequently causes unreadability. Do you
think you could dense it down a little, please?
> diff --git a/epoch.c b/epoch.c
> --- a/epoch.c
> +++ b/epoch.c
> @@ -450,11 +450,15 @@ static void mark_ancestors_uninteresting
> // Sorts the nodes of the first epoch of the epoch sequence of the epoch headed at head
> // into merge order.
> //
> -static void sort_first_epoch(struct commit *head, struct commit_list **stack)
> +static void sort_first_epoch(struct commit *head, struct commit_list **stack, marker_func marker)
> {
> struct commit_list *parents;
> struct commit_list *reversed_parents = NULL;
>
> + if (marker) {
> + (*marker)(head);
> + }
> +
> head->object.flags |= VISITED;
These whitespaces seem quite strange too. Check your editor settings.
;-)
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
[not found] ` <2cfc403205060702596dee7341@mail.gmail.com>
@ 2005-06-07 15:58 ` Jon Seymour
0 siblings, 0 replies; 10+ messages in thread
From: Jon Seymour @ 2005-06-07 15:58 UTC (permalink / raw)
To: Git Mailing List
> --wrt-author helps to reconstruct the merge-history from the
> perspective of each individual committer.
>
Correction:
--wrt-author helps to reconstruct the merge-history from the
perspective of each individual author.
jon.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
[not found] ` <2cfc403205060702594da21fb1@mail.gmail.com>
[not found] ` <2cfc403205060702596dee7341@mail.gmail.com>
@ 2005-06-08 0:54 ` Jon Seymour
2005-06-08 8:58 ` Petr Baudis
2 siblings, 0 replies; 10+ messages in thread
From: Jon Seymour @ 2005-06-08 0:54 UTC (permalink / raw)
To: Git Mailing List
| not sure why, but my first attempt to post this to the list didn't
seem to make it
| I've also modified my response slightly to suggest an alternate name for the
| --exclude-author swtich which may partly address pasky's concerns. amended
| response marked with ***
On 6/7/05, Petr Baudis <pasky@ucw.cz> wrote:
>
> I'd prefer just --wrt-author and --exclude-author to take an argument on
> their own.
The reason I don't want to do this is that it doesn't really make
sense in the context of the change to specify one author for
--wrt-author and another for --exclude-author. In normal use --author
defaults to GIT_AUTHOR_EMAIL or the locally derived user@host.domain.
The intention is simply to override this default derivation.
*** That said, it might better if --exclude-author was called
something like --following-author --after-author or --stop-at-author,
since its meaning is to stop traversal rather than simply omit match
entries which is the meaning that a reasonable user might attach to
use of the word "exclude"
My preference is --following-author.
Thoughts anyone?
>
> (Note that I don't endorse this patch and the --wrt-author behaviour in
> particular seems strange. I don't have enough time to comment on it
> sensibly now, though. I'm just focusing on style here since I'd like to
> still be able to read git's source code few weeks from now on.)
The rationale for the change is as follows:
During parallel development, one is aware of ones own
changes...everyone else changes haven't happened yet as far as you are
concerned. Only when they appear in a future merge that incorporates
one's own changes do the other changes appear in your own workspace.
As far as you are concerned, these changes occurred after you made
your own - your changes were not dependent on those changes, only on
those that came before. So the linearisation reflects that perceived
ordering of changes.
--wrt-author helps to reconstruct the merge-history from the
perspective of each individual committer.
Let me know if this doesn't explain the rationale completely enough
for your understanding.
jon.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
[not found] ` <2cfc403205060702594da21fb1@mail.gmail.com>
[not found] ` <2cfc403205060702596dee7341@mail.gmail.com>
2005-06-08 0:54 ` Jon Seymour
@ 2005-06-08 8:58 ` Petr Baudis
2005-06-08 9:31 ` Jon Seymour
2 siblings, 1 reply; 10+ messages in thread
From: Petr Baudis @ 2005-06-08 8:58 UTC (permalink / raw)
To: Jon Seymour; +Cc: git
Dear diary, on Tue, Jun 07, 2005 at 11:59:36AM CEST, I got a letter
where Jon Seymour <jon.seymour@gmail.com> told me that...
> On 6/7/05, Petr Baudis <pasky@ucw.cz> wrote:
> > I'd prefer just --wrt-author and --exclude-author to take an argument on
> > their own.
>
> The reason I don't want to do this is that it doesn't really make
> sense in the context of the change to specify one author for
> --wrt-author and another for --exclude-author. In normal use --author
> defaults to GIT_AUTHOR_EMAIL or the locally derived user@host.domain.
> The intention is simply to override this default derivation.
Hmm, then why not make it --wrt-author[=AUTHOR] ? Similar to the
--pretty option. BTW, can it do multiple author excludes now? The
commandline would look especially horrifying in that case now, I guess.
I'd prefer --stop-at-author from the choices you offer in your other
mail.
> > (Note that I don't endorse this patch and the --wrt-author behaviour in
> > particular seems strange. I don't have enough time to comment on it
> > sensibly now, though. I'm just focusing on style here since I'd like to
> > still be able to read git's source code few weeks from now on.)
>
> The rationale for the change is as follows:
>
> During parallel development, one is aware of ones own
> changes...everyone else changes haven't happened yet as far as you are
> concerned. Only when they appear in a future merge that incorporates
> one's own changes do the other changes appear in your own workspace.
>
> As far as you are concerned, these changes occurred after you made
> your own - your changes were not dependent on those changes, only on
> those that came before. So the linearisation reflects that perceived
> ordering of changes.
>
> --wrt-author helps to reconstruct the merge-history from the
> perspective of each individual committer.
Yes, such motivation makes sense. But is the author field the right one?
If you are integrating a lot of other people's patches in particular, I
think it makes no sense whatsoever - you already reviewed and
consciously applied them, but your option will regard them as something
alien and merged from outside, right?
And, after all, the other branches might be _quite_ long-lived. I think
it would be confusing for the user if the commit graph looked like
a1 -- a2 -- a3 -- a4 -- a5 -- a6 -- a7 -- a8 -- a9 -- a10
\ / / \ /
- b1 -- b2 -- b3 -- b4 -- b5 -- b6 -- b7 -- b8 -- b9
If your patch first chooses b1, it then shows all of it, completely
ignoring a2, right? I can't see how that would be right - the subsequent
merges from a should be shown.
--
Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
2005-06-08 8:58 ` Petr Baudis
@ 2005-06-08 9:31 ` Jon Seymour
2005-06-08 10:52 ` Jon Seymour
2005-06-08 11:14 ` Jon Seymour
0 siblings, 2 replies; 10+ messages in thread
From: Jon Seymour @ 2005-06-08 9:31 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
On 6/8/05, Petr Baudis <pasky@ucw.cz> wrote:
> Dear diary, on Tue, Jun 07, 2005 at 11:59:36AM CEST, I got a letter
> where Jon Seymour <jon.seymour@gmail.com> told me that...
> > On 6/7/05, Petr Baudis <pasky@ucw.cz> wrote:
> > > I'd prefer just --wrt-author and --exclude-author to take an argument on
> > > their own.
> >
> > The reason I don't want to do this is that it doesn't really make
> > sense in the context of the change to specify one author for
> > --wrt-author and another for --exclude-author. In normal use --author
> > defaults to GIT_AUTHOR_EMAIL or the locally derived user@host.domain.
> > The intention is simply to override this default derivation.
>
> Hmm, then why not make it --wrt-author[=AUTHOR] ? Similar to the
> --pretty option. BTW, can it do multiple author excludes now? The
> commandline would look especially horrifying in that case now, I guess.
>
No, it doesn't. I can see a use for multiple ^ arguments, but the use
case for multiple --stop-at-author arguments doesn't strike me as
being particularly useful. Multiple ^'s helps you prune the graph at
places you already know about --stop-at-author allows you to prune the
tree with respect to one author. It is particularly useful if you are
the author concerned because you have some recollection of being of
what you did last. I am not sure it is that useful to prune the tree
with respect to multiple authors - the results would be somewhat
unpredictable, I would think.
> I'd prefer --stop-at-author from the choices you offer in your other
> mail.
>
Ok, unless I Linus or the list disagree I will modify my patch to be
--stop-at-author.
> > > (Note that I don't endorse this patch and the --wrt-author behaviour in
> > > particular seems strange. I don't have enough time to comment on it
> > > sensibly now, though. I'm just focusing on style here since I'd like to
> > > still be able to read git's source code few weeks from now on.)
> >
> > The rationale for the change is as follows:
> >
> > During parallel development, one is aware of ones own
> > changes...everyone else changes haven't happened yet as far as you are
> > concerned. Only when they appear in a future merge that incorporates
> > one's own changes do the other changes appear in your own workspace.
> >
> > As far as you are concerned, these changes occurred after you made
> > your own - your changes were not dependent on those changes, only on
> > those that came before. So the linearisation reflects that perceived
> > ordering of changes.
> >
> > --wrt-author helps to reconstruct the merge-history from the
> > perspective of each individual committer.
>
> Yes, such motivation makes sense. But is the author field the right one?
> If you are integrating a lot of other people's patches in particular, I
> think it makes no sense whatsoever - you already reviewed and
> consciously applied them, but your option will regard them as something
> alien and merged from outside, right?
>
> And, after all, the other branches might be _quite_ long-lived. I think
> it would be confusing for the user if the commit graph looked like
>
> a1 -- a2 -- a3 -- a4 -- a5 -- a6 -- a7 -- a8 -- a9 -- a10
> \ / / \ /
> - b1 -- b2 -- b3 -- b4 -- b5 -- b6 -- b7 -- b8 -- b9
>
> If your patch first chooses b1, it then shows all of it, completely
> ignoring a2, right? I can't see how that would be right - the subsequent
> merges from a should be shown.
No, that's not the intent of --wrt-author when specified without
--stop-at-author.
--wrt-author doesn't cause any commits to be ignored ... it simply
changes the order
in which they are displayed by altering the order in which parents are visited.
I'll get it wrong if I do it by hand so I'll create a test case and
show you what the default merge order would be, the --wrt-author
--author=a and the --wrt-author --author=b cases.
Stay tuned...
jon.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
2005-06-08 9:31 ` Jon Seymour
@ 2005-06-08 10:52 ` Jon Seymour
2005-06-08 11:14 ` Jon Seymour
1 sibling, 0 replies; 10+ messages in thread
From: Jon Seymour @ 2005-06-08 10:52 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
Ok, this is how --wrt-author sorts your example:
(Original example transposed so that variable width fonts don't play
havoc with the layout)
a10 b9
| \ |
a9 b8
| |
a8 b7
| |
a7 b6
| / |
a6 b5
| \ |
a5 b4
| |
a4 b3
| \ |
a3 b2
| |
a2 b1
| /
a1
with respect to a and b respectively
A B
| b9 | b9
^ a10 ^ a10
| b8 | a9
| b7 | a8
| b6 | a7
| b5 ^ b8
^ a9 | b7
| a8 | b6
| a7 | a6
| a6 | a5
| b4 | a4
| b3 | a3
^ a5 | a2
| a4 ^ b5
| b2 | b4
| b1 | b3
^ a3 | b2
| a2 | b1
= a1 = a1
In otherwords, B doesn't see any of A's changes after a1 until b6,
whereas A sees some of B's changes at a4 and some at a6, then not
again until a10.
jon.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
2005-06-08 9:31 ` Jon Seymour
2005-06-08 10:52 ` Jon Seymour
@ 2005-06-08 11:14 ` Jon Seymour
2005-06-08 16:36 ` [WITHDRAW PATCH] " Jon Seymour
1 sibling, 1 reply; 10+ messages in thread
From: Jon Seymour @ 2005-06-08 11:14 UTC (permalink / raw)
To: Petr Baudis; +Cc: git
Pasky,
Hey, I was thinking, instead of stop-at-author, how about we call it
prune-at-author instead?
Regards,
jon.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [WITHDRAW PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
2005-06-08 11:14 ` Jon Seymour
@ 2005-06-08 16:36 ` Jon Seymour
0 siblings, 0 replies; 10+ messages in thread
From: Jon Seymour @ 2005-06-08 16:36 UTC (permalink / raw)
To: git; +Cc: Linus Torvalds
G'day Linus,
I'd like to withdraw this patch until the --merge-order bug fix of my
earlier post is applied. The patch as it stands won't operate
correctly once that fix is applied, so I'll have to modify it. Also, I
want to rename the --exclude-author switch to --prune-at-author.
Regards,
jon.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2005-06-08 16:45 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-07 9:15 [PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list Jon Seymour
2005-06-07 9:30 ` Jon Seymour
2005-06-07 9:49 ` Petr Baudis
[not found] ` <2cfc403205060702594da21fb1@mail.gmail.com>
[not found] ` <2cfc403205060702596dee7341@mail.gmail.com>
2005-06-07 15:58 ` Jon Seymour
2005-06-08 0:54 ` Jon Seymour
2005-06-08 8:58 ` Petr Baudis
2005-06-08 9:31 ` Jon Seymour
2005-06-08 10:52 ` Jon Seymour
2005-06-08 11:14 ` Jon Seymour
2005-06-08 16:36 ` [WITHDRAW PATCH] " Jon Seymour
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).