9 static char *path_name(struct name_path
*path
, const char *name
)
13 int nlen
= strlen(name
);
16 for (p
= path
; p
; p
= p
->up
) {
18 len
+= p
->elem_len
+ 1;
21 m
= n
+ len
- (nlen
+ 1);
23 for (p
= path
; p
; p
= p
->up
) {
26 memcpy(m
, p
->elem
, p
->elem_len
);
33 struct object_list
**add_object(struct object
*obj
,
34 struct object_list
**p
,
35 struct name_path
*path
,
38 struct object_list
*entry
= xmalloc(sizeof(*entry
));
41 entry
->name
= path_name(path
, name
);
46 static void mark_blob_uninteresting(struct blob
*blob
)
48 if (blob
->object
.flags
& UNINTERESTING
)
50 blob
->object
.flags
|= UNINTERESTING
;
53 void mark_tree_uninteresting(struct tree
*tree
)
55 struct object
*obj
= &tree
->object
;
56 struct tree_entry_list
*entry
;
58 if (obj
->flags
& UNINTERESTING
)
60 obj
->flags
|= UNINTERESTING
;
61 if (!has_sha1_file(obj
->sha1
))
63 if (parse_tree(tree
) < 0)
64 die("bad tree %s", sha1_to_hex(obj
->sha1
));
65 entry
= tree
->entries
;
68 struct tree_entry_list
*next
= entry
->next
;
70 mark_tree_uninteresting(entry
->item
.tree
);
72 mark_blob_uninteresting(entry
->item
.blob
);
78 void mark_parents_uninteresting(struct commit
*commit
)
80 struct commit_list
*parents
= commit
->parents
;
83 struct commit
*commit
= parents
->item
;
84 commit
->object
.flags
|= UNINTERESTING
;
87 * Normally we haven't parsed the parent
88 * yet, so we won't have a parent of a parent
89 * here. However, it may turn out that we've
90 * reached this commit some other way (where it
91 * wasn't uninteresting), in which case we need
92 * to mark its parents recursively too..
95 mark_parents_uninteresting(commit
);
98 * A missing commit is ok iff its parent is marked
101 * We just mark such a thing parsed, so that when
102 * it is popped next time around, we won't be trying
103 * to parse it and get an error.
105 if (!has_sha1_file(commit
->object
.sha1
))
106 commit
->object
.parsed
= 1;
107 parents
= parents
->next
;
111 static void add_pending_object(struct rev_info
*revs
, struct object
*obj
, const char *name
)
113 add_object(obj
, &revs
->pending_objects
, NULL
, name
);
116 static struct commit
*get_commit_reference(struct rev_info
*revs
, const char *name
, const unsigned char *sha1
, unsigned int flags
)
118 struct object
*object
;
120 object
= parse_object(sha1
);
122 die("bad object %s", name
);
125 * Tag object? Look what it points to..
127 while (object
->type
== tag_type
) {
128 struct tag
*tag
= (struct tag
*) object
;
129 object
->flags
|= flags
;
130 if (revs
->tag_objects
&& !(object
->flags
& UNINTERESTING
))
131 add_pending_object(revs
, object
, tag
->tag
);
132 object
= parse_object(tag
->tagged
->sha1
);
134 die("bad object %s", sha1_to_hex(tag
->tagged
->sha1
));
138 * Commit object? Just return it, we'll do all the complex
141 if (object
->type
== commit_type
) {
142 struct commit
*commit
= (struct commit
*)object
;
143 object
->flags
|= flags
;
144 if (parse_commit(commit
) < 0)
145 die("unable to parse commit %s", name
);
146 if (flags
& UNINTERESTING
) {
147 mark_parents_uninteresting(commit
);
154 * Tree object? Either mark it uniniteresting, or add it
155 * to the list of objects to look at later..
157 if (object
->type
== tree_type
) {
158 struct tree
*tree
= (struct tree
*)object
;
159 if (!revs
->tree_objects
)
161 if (flags
& UNINTERESTING
) {
162 mark_tree_uninteresting(tree
);
165 add_pending_object(revs
, object
, "");
170 * Blob object? You know the drill by now..
172 if (object
->type
== blob_type
) {
173 struct blob
*blob
= (struct blob
*)object
;
174 if (!revs
->blob_objects
)
176 if (flags
& UNINTERESTING
) {
177 mark_blob_uninteresting(blob
);
180 add_pending_object(revs
, object
, "");
183 die("%s is unknown object", name
);
186 static void add_one_commit(struct commit
*commit
, struct rev_info
*revs
)
188 if (!commit
|| (commit
->object
.flags
& SEEN
))
190 commit
->object
.flags
|= SEEN
;
191 commit_list_insert(commit
, &revs
->commits
);
194 static int all_flags
;
195 static struct rev_info
*all_revs
;
197 static int handle_one_ref(const char *path
, const unsigned char *sha1
)
199 struct commit
*commit
= get_commit_reference(all_revs
, path
, sha1
, all_flags
);
200 add_one_commit(commit
, all_revs
);
204 static void handle_all(struct rev_info
*revs
, unsigned flags
)
208 for_each_ref(handle_one_ref
);
212 * Parse revision information, filling in the "rev_info" structure,
213 * and removing the used arguments from the argument list.
215 * Returns the number of arguments left ("new argc").
217 int setup_revisions(int argc
, const char **argv
, struct rev_info
*revs
)
219 int i
, flags
, seen_dashdash
;
220 const char *def
= NULL
;
221 const char **unrecognized
= argv
+1;
224 memset(revs
, 0, sizeof(*revs
));
227 revs
->prefix
= setup_git_directory();
230 revs
->max_count
= -1;
232 /* First, search for "--" */
234 for (i
= 1; i
< argc
; i
++) {
235 const char *arg
= argv
[i
];
236 if (strcmp(arg
, "--"))
240 revs
->paths
= get_pathspec(revs
->prefix
, argv
+ i
+ 1);
246 for (i
= 1; i
< argc
; i
++) {
247 struct commit
*commit
;
248 const char *arg
= argv
[i
];
249 unsigned char sha1
[20];
254 if (!strncmp(arg
, "--max-count=", 12)) {
255 revs
->max_count
= atoi(arg
+ 12);
258 if (!strncmp(arg
, "--max-age=", 10)) {
259 revs
->max_age
= atoi(arg
+ 10);
263 if (!strncmp(arg
, "--min-age=", 10)) {
264 revs
->min_age
= atoi(arg
+ 10);
268 if (!strcmp(arg
, "--all")) {
269 handle_all(revs
, flags
);
272 if (!strcmp(arg
, "--not")) {
273 flags
^= UNINTERESTING
;
276 if (!strcmp(arg
, "--default")) {
278 die("bad --default argument");
282 if (!strcmp(arg
, "--topo-order")) {
283 revs
->topo_order
= 1;
287 if (!strcmp(arg
, "--date-order")) {
289 revs
->topo_order
= 1;
293 if (!strcmp(arg
, "--dense")) {
297 if (!strcmp(arg
, "--sparse")) {
301 if (!strcmp(arg
, "--remove-empty")) {
302 revs
->remove_empty_trees
= 1;
305 if (!strcmp(arg
, "--objects")) {
306 revs
->tag_objects
= 1;
307 revs
->tree_objects
= 1;
308 revs
->blob_objects
= 1;
311 if (!strcmp(arg
, "--objects-edge")) {
312 revs
->tag_objects
= 1;
313 revs
->tree_objects
= 1;
314 revs
->blob_objects
= 1;
318 if (!strcmp(arg
, "--unpacked")) {
323 *unrecognized
++ = arg
;
327 dotdot
= strstr(arg
, "..");
329 unsigned char from_sha1
[20];
330 char *next
= dotdot
+ 2;
334 if (!get_sha1(arg
, from_sha1
) && !get_sha1(next
, sha1
)) {
335 struct commit
*exclude
;
336 struct commit
*include
;
338 exclude
= get_commit_reference(revs
, arg
, from_sha1
, flags
^ UNINTERESTING
);
339 include
= get_commit_reference(revs
, next
, sha1
, flags
);
340 if (!exclude
|| !include
)
341 die("Invalid revision range %s..%s", arg
, next
);
342 add_one_commit(exclude
, revs
);
343 add_one_commit(include
, revs
);
350 local_flags
= UNINTERESTING
;
353 if (get_sha1(arg
, sha1
) < 0) {
357 if (seen_dashdash
|| local_flags
)
358 die("bad revision '%s'", arg
);
360 /* If we didn't have a "--", all filenames must exist */
361 for (j
= i
; j
< argc
; j
++) {
362 if (lstat(argv
[j
], &st
) < 0)
363 die("'%s': %s", arg
, strerror(errno
));
365 revs
->paths
= get_pathspec(revs
->prefix
, argv
+ i
);
368 commit
= get_commit_reference(revs
, arg
, sha1
, flags
^ local_flags
);
369 add_one_commit(commit
, revs
);
371 if (def
&& !revs
->commits
) {
372 unsigned char sha1
[20];
373 struct commit
*commit
;
374 if (get_sha1(def
, sha1
) < 0)
375 die("bad default revision '%s'", def
);
376 commit
= get_commit_reference(revs
, def
, sha1
, 0);
377 add_one_commit(commit
, revs
);
381 *unrecognized
= NULL
;