commit - 29606af7a3a58767bf817a38035490899609d13e
commit + b8bad2ba42b397e4040667df22fbd795f6c796f6
blob - 6148cc965ebf17c3b6dd0d792bd4f3d7261ddb6e
blob + 9ae1a22c521640c7b65b692d41af663d2e4fb9df
--- got/got.c
+++ got/got.c
path = in_repo_path;
}
- error = got_ref_list(&refs, repo, NULL);
+ error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
if (error)
goto done;
struct got_reflist_entry *re;
SIMPLEQ_INIT(&refs);
- err = got_ref_list(&refs, repo, NULL);
+ err = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
if (err)
return err;
SIMPLEQ_INIT(&refs);
- err = got_ref_list(&refs, repo, "refs/heads");
+ err = got_ref_list(&refs, repo, "refs/heads",
+ got_ref_cmp_by_name, NULL);
if (err)
return err;
"usage: %s tag [-r repository] | -l | "
"[-m message] name [commit]\n", getprogname());
exit(1);
+}
+
+#if 0
+static const struct got_error *
+sort_tags(struct got_reflist_head *sorted, struct got_reflist_head *tags)
+{
+ const struct got_error *err = NULL;
+ struct got_reflist_entry *re, *se, *new;
+ struct got_object_id *re_id, *se_id;
+ struct got_tag_object *re_tag, *se_tag;
+ time_t re_time, se_time;
+
+ SIMPLEQ_FOREACH(re, tags, entry) {
+ se = SIMPLEQ_FIRST(sorted);
+ if (se == NULL) {
+ err = got_reflist_entry_dup(&new, re);
+ if (err)
+ return err;
+ SIMPLEQ_INSERT_HEAD(sorted, new, entry);
+ continue;
+ } else {
+ err = got_ref_resolve(&re_id, repo, re->ref);
+ if (err)
+ break;
+ err = got_object_open_as_tag(&re_tag, repo, re_id);
+ free(re_id);
+ if (err)
+ break;
+ re_time = got_object_tag_get_tagger_time(re_tag);
+ got_object_tag_close(re_tag);
+ }
+
+ while (se) {
+ err = got_ref_resolve(&se_id, repo, re->ref);
+ if (err)
+ break;
+ err = got_object_open_as_tag(&se_tag, repo, se_id);
+ free(se_id);
+ if (err)
+ break;
+ se_time = got_object_tag_get_tagger_time(se_tag);
+ got_object_tag_close(se_tag);
+
+ if (se_time > re_time) {
+ err = got_reflist_entry_dup(&new, re);
+ if (err)
+ return err;
+ SIMPLEQ_INSERT_AFTER(sorted, se, new, entry);
+ break;
+ }
+ se = SIMPLEQ_NEXT(se, entry);
+ continue;
+ }
+ }
+done:
+ return err;
}
+#endif
static const struct got_error *
+cmp_tags(void *arg, int *cmp, struct got_reference *ref1,
+ struct got_reference *ref2)
+{
+ const struct got_error *err = NULL;
+ struct got_repository *repo = arg;
+ struct got_object_id *id1, *id2 = NULL;
+ struct got_tag_object *tag1 = NULL, *tag2 = NULL;
+ time_t time1, time2;
+
+ *cmp = 0;
+
+ err = got_ref_resolve(&id1, repo, ref1);
+ if (err)
+ return err;
+ err = got_object_open_as_tag(&tag1, repo, id1);
+ if (err)
+ goto done;
+
+ err = got_ref_resolve(&id2, repo, ref2);
+ if (err)
+ goto done;
+ err = got_object_open_as_tag(&tag2, repo, id2);
+ if (err)
+ goto done;
+
+ time1 = got_object_tag_get_tagger_time(tag1);
+ time2 = got_object_tag_get_tagger_time(tag2);
+
+ /* Put latest tags first. */
+ if (time1 < time2)
+ *cmp = 1;
+ else if (time1 > time2)
+ *cmp = -1;
+ else
+ err = got_ref_cmp_by_name(NULL, cmp, ref2, ref1);
+done:
+ free(id1);
+ free(id2);
+ if (tag1)
+ got_object_tag_close(tag1);
+ if (tag2)
+ got_object_tag_close(tag2);
+ return err;
+}
+
+static const struct got_error *
list_tags(struct got_repository *repo, struct got_worktree *worktree)
{
static const struct got_error *err = NULL;
SIMPLEQ_INIT(&refs);
- err = got_ref_list(&refs, repo, "refs/tags");
+ err = got_ref_list(&refs, repo, "refs/tags", cmp_tags, repo);
if (err)
return err;
blob - 67fa4cc7d1bd16dc97d7c1f3fb658a7d84b9d4ab
blob + 50ff76771483d382370d47f5134048a4573e6788
--- include/got_reference.h
+++ include/got_reference.h
};
SIMPLEQ_HEAD(got_reflist_head, got_reflist_entry);
+/* Duplicate a reference list entry. Caller must dispose of it with free(3). */
+const struct got_error *got_reflist_entry_dup(struct got_reflist_entry **,
+ struct got_reflist_entry *);
+
+/* A function which compares two references. Used with got_ref_list(). */
+typedef const struct got_error *(*got_ref_cmp_cb)(void *, int *,
+ struct got_reference *, struct got_reference *);
+
+/* An implementation of got_ref_cmp_cb which compares two references by name. */
+const struct got_error *got_ref_cmp_by_name(void *, int *,
+ struct got_reference *, struct got_reference *);
+
/*
* Append all known references to a caller-provided ref list head.
* Optionally limit references returned to those within a given
- * reference namespace.
+ * reference namespace. Sort the list with the provided reference comparison
+ * function, usually got_ref_cmp_by_name().
*/
const struct got_error *got_ref_list(struct got_reflist_head *,
- struct got_repository *, const char *);
+ struct got_repository *, const char *, got_ref_cmp_cb, void *);
/* Free all references on a ref list. */
void got_ref_list_free(struct got_reflist_head *);
blob - 27bcf86d4d2492625ca6d33f449ada7ce71b6c69
blob + c4723d5692b318f338242ac11195e9f2a00f13a9
--- lib/reference.c
+++ lib/reference.c
return ret;
}
+
+const struct got_error *
+got_reflist_entry_dup(struct got_reflist_entry **newp,
+ struct got_reflist_entry *re)
+{
+ const struct got_error *err = NULL;
+ struct got_reflist_entry *new;
+
+ *newp = NULL;
+
+ new = malloc(sizeof(*new));
+ if (new == NULL)
+ return got_error_from_errno("malloc");
+ new->ref = got_ref_dup(re->ref);
+ if (new->ref == NULL) {
+ err = got_error_from_errno("got_ref_dup");
+ free(new);
+ return err;
+ }
+
+ new->id = got_object_id_dup(re->id);
+ if (new->id == NULL) {
+ err = got_error_from_errno("got_ref_dup");
+ free(new->id);
+ free(new);
+ return err;
+ }
+
+ *newp = new;
+ return NULL;
+}
+
static const struct got_error *
resolve_symbolic_ref(struct got_reference **resolved,
struct got_repository *repo, struct got_reference *ref)
{
if (ref->flags & GOT_REF_IS_SYMBOLIC)
return ref->ref.symref.ref;
+
+ return NULL;
+}
+
+const struct got_error *
+got_ref_cmp_by_name(void *arg, int *cmp, struct got_reference *re1,
+ struct got_reference* re2)
+{
+ const char *name1 = got_ref_get_name(re1);
+ const char *name2 = got_ref_get_name(re2);
+ *cmp = got_path_cmp(name1, name2, strlen(name1), strlen(name2));
return NULL;
}
static const struct got_error *
insert_ref(struct got_reflist_entry **newp, struct got_reflist_head *refs,
- struct got_reference *ref, struct got_repository *repo)
+ struct got_reference *ref, struct got_repository *repo,
+ got_ref_cmp_cb cmp_cb, void *cmp_arg)
{
const struct got_error *err;
struct got_object_id *id;
*/
re = SIMPLEQ_FIRST(refs);
while (re) {
- const char *name = got_ref_get_name(re->ref);
- const char *new_name = got_ref_get_name(new->ref);
- cmp = got_path_cmp(name, new_name, strlen(name),
- strlen(new_name));
+ err = (*cmp_cb)(cmp_arg, &cmp, re->ref, new->ref);
+ if (err)
+ return err;
if (cmp == 0) {
/* duplicate */
free(new->id);
static const struct got_error *
gather_on_disk_refs(struct got_reflist_head *refs, const char *path_refs,
- const char *subdir, struct got_repository *repo)
+ const char *subdir, struct got_repository *repo,
+ got_ref_cmp_cb cmp_cb, void *cmp_arg)
{
const struct got_error *err = NULL;
DIR *d = NULL;
goto done;
if (ref) {
struct got_reflist_entry *new;
- err = insert_ref(&new, refs, ref, repo);
+ err = insert_ref(&new, refs, ref, repo,
+ cmp_cb, cmp_arg);
if (err || new == NULL /* duplicate */)
got_ref_close(ref);
if (err)
err = got_error_from_errno("asprintf");
break;
}
- err = gather_on_disk_refs(refs, path_refs, child, repo);
+ err = gather_on_disk_refs(refs, path_refs, child, repo,
+ cmp_cb, cmp_arg);
free(child);
break;
default:
const struct got_error *
got_ref_list(struct got_reflist_head *refs, struct got_repository *repo,
- const char *ref_namespace)
+ const char *ref_namespace, got_ref_cmp_cb cmp_cb, void *cmp_arg)
{
const struct got_error *err;
char *packed_refs_path, *path_refs = NULL;
err = open_ref(&ref, path_refs, "", GOT_REF_HEAD, 0);
if (err)
goto done;
- err = insert_ref(&new, refs, ref, repo);
+ err = insert_ref(&new, refs, ref, repo, cmp_cb, cmp_arg);
if (err || new == NULL /* duplicate */)
got_ref_close(ref);
if (err)
goto done;
}
err = gather_on_disk_refs(refs, path_refs,
- ref_namespace ? ref_namespace : "", repo);
+ ref_namespace ? ref_namespace : "", repo, cmp_cb, cmp_arg);
if (err)
goto done;
continue;
}
}
- err = insert_ref(&new, refs, ref, repo);
+ err = insert_ref(&new, refs, ref, repo,
+ cmp_cb, cmp_arg);
if (err || new == NULL /* duplicate */)
got_ref_close(ref);
if (err)
continue;
}
- err = insert_ref(&new, &refs, ref, repo);
+ err = insert_ref(&new, &refs, ref, repo,
+ got_ref_cmp_by_name, NULL);
if (err || new == NULL /* duplicate */)
got_ref_close(ref);
if (err)
blob - 4ed88ead1f4f6151d23365d58166fb12931f06e7
blob + eeffa65542fb24958cb041d67effcdf464713ded
--- lib/repository.c
+++ lib/repository.c
SIMPLEQ_INIT(&refs);
*tag = NULL;
- err = got_ref_list(&refs, repo, "refs/tags");
+ err = got_ref_list(&refs, repo, "refs/tags", got_ref_cmp_by_name, NULL);
if (err)
return err;
blob - dd28ecc607e0e077b5ab8ef39621b8e522e0ae52
blob + db9528a8d563d08559533e1edb30d63c3e7a4beb
--- regress/cmdline/tag.sh
+++ regress/cmdline/tag.sh
echo "-----------------------------------------------" \
> $testroot/stdout.expected
- echo "tag $tag $tag_id" >> $testroot/stdout.expected
+ echo "tag $tag2 $tag_id2" >> $testroot/stdout.expected
echo "from: $GOT_AUTHOR" >> $testroot/stdout.expected
echo "date: $d1" >> $testroot/stdout.expected
echo "object: commit $commit_id" >> $testroot/stdout.expected
echo " " >> $testroot/stdout.expected
echo "-----------------------------------------------" \
>> $testroot/stdout.expected
- echo "tag $tag2 $tag_id2" >> $testroot/stdout.expected
+ echo "tag $tag $tag_id" >> $testroot/stdout.expected
echo "from: $GOT_AUTHOR" >> $testroot/stdout.expected
echo "date: $d2" >> $testroot/stdout.expected
echo "object: commit $commit_id" >> $testroot/stdout.expected
blob - a1865a54165076e33e14a3daa3b0728f43f23017
blob + d5a10ac995e03463cd40984b797f33f7f214f61d
--- tog/tog.c
+++ tog/tog.c
if (error != NULL)
goto done;
- error = got_ref_list(&refs, repo, NULL);
+ error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
if (error)
goto done;
if (error)
goto done;
- error = got_ref_list(&refs, repo, NULL);
+ error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
if (error)
goto done;
if (error != NULL)
goto done;
- error = got_ref_list(&refs, repo, NULL);
+ error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
if (error)
goto done;
if (error != NULL)
goto done;
- error = got_ref_list(&refs, repo, NULL);
+ error = got_ref_list(&refs, repo, NULL, got_ref_cmp_by_name, NULL);
if (error)
goto done;