"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: implement sort by date in tog ref
To:
gameoftrees@openbsd.org
Date:
Sat, 20 Nov 2021 23:04:15 +0100

Download raw body.

Thread
On Tue, Nov 16, 2021 at 03:43:21PM +0100, Stefan Sperling wrote:
> I tend to get lost between changes that are stacked on top of each
> other sometimes. Often, each change in the stack will have a branch
> reference pointing at it so I can keep track of things more easily.
> 
> However, finding the top of this stack (i.e. the most recently modified
> branc) is not trivial with our current UI. It essentially requires
> jumping between references and comparing their commit date manually.
> 
> This patch adds an easy way: Press 's' in the tog ref view and all
> references will be sorted by their commit timestamp. In the weird
> case where a ref does not point at a commit or tag we use the last
> modification time of the on-disk reference file as a fallback.
> 
> ok?

I have committed this patch along with some follow-up fixes and tweaks.

> Perhaps later we could add new options to allow 'got ref -l' and
> 'got branch -l' to sort by date as well?
> 
> diff f8306a31050978f1e7ff99ae008c68c4edf0678f c272759fa2c91227825d4eba4d9df8e784a56b25
> blob - 23650d4ec25dae858e6e634a02dd5735b0ac0b9d
> blob + 3d4dadc8459f1d8ea2df85a31273afae7074548f
> --- lib/reference.c
> +++ lib/reference.c
> @@ -769,50 +769,76 @@ done:
>  	return err;
>  }
>  
> +static const struct got_error *
> +get_committer_time(struct got_reference *ref, struct got_repository *repo)
> +{
> +	const struct got_error *err = NULL;
> +	int obj_type;
> +	struct got_commit_object *commit = NULL;
> +	struct got_tag_object *tag = NULL;
> +	struct got_object_id *id = NULL;
> +
> +	err = got_ref_resolve(&id, repo, ref);
> +	if (err)
> +		return err;
> +
> +	err = got_object_get_type(&obj_type, repo, id);
> +	if (err)
> +		goto done;
> +
> +	switch (obj_type) {
> +	case GOT_OBJ_TYPE_COMMIT:
> +		err = got_object_open_as_commit(&commit, repo, id);
> +		if (err)
> +			goto done;
> +		ref->committer_time =
> +		    got_object_commit_get_committer_time(commit);
> +		break;
> +	case GOT_OBJ_TYPE_TAG:
> +		err = got_object_open_as_tag(&tag, repo, id);
> +		if (err)
> +			goto done;
> +		ref->committer_time = got_object_tag_get_tagger_time(tag);
> +		break;
> +	default:
> +		/* best effort for other object types */
> +		ref->committer_time = got_ref_get_mtime(ref);
> +		break;
> +	}
> +done:
> +	free(id);
> +	if (commit)
> +		got_object_commit_close(commit);
> +	if (tag)
> +		got_object_tag_close(tag);
> +	return err;
> +}
> +
>  const struct got_error *
>  got_ref_cmp_by_commit_timestamp_descending(void *arg, int *cmp,
>      struct got_reference *ref1, struct got_reference *ref2)
>  {
>  	const struct got_error *err;
>  	struct got_repository *repo = arg;
> -	struct got_object_id *id1 = NULL, *id2 = NULL;
> -	struct got_commit_object *commit1 = NULL, *commit2 = NULL;
>  
>  	*cmp = 0;
>  
>  	if (ref1->committer_time == 0) {
> -		err = got_ref_resolve(&id1, repo, ref1);
> +		err = get_committer_time(ref1, repo);
>  		if (err)
>  			return err;
> -		err = got_object_open_as_commit(&commit1, repo, id1);
> -		if (err)
> -			goto done;
> -		ref1->committer_time =
> -		    got_object_commit_get_committer_time(commit1);
>  	}
> -
>  	if (ref2->committer_time == 0) {
> -		err = got_ref_resolve(&id2, repo, ref2);
> +		err = get_committer_time(ref2, repo);
>  		if (err)
>  			return err;
> -		err = got_object_open_as_commit(&commit2, repo, id2);
> -		if (err)
> -			goto done;
> -		ref2->committer_time =
> -		    got_object_commit_get_committer_time(commit2);
>  	}
>  
>  	if (ref1->committer_time < ref2->committer_time)
>  		*cmp = 1;
>  	else if (ref2->committer_time < ref1->committer_time)
>  		*cmp = -1;
> -done:
> -	free(id1);
> -	free(id2);
> -	if (commit1)
> -		got_object_commit_close(commit1);
> -	if (commit2)
> -		got_object_commit_close(commit2);
> +
>  	return err;
>  }
>  
> blob - 0e414ba8af3db6bb003ec9b35d7e1510d7c18632
> blob + 838d2ac721da6d2d566440db6d4fe96c55d79cec
> --- tog/tog.1
> +++ tog/tog.1
> @@ -452,6 +452,8 @@ view showing the tree resolved via the currently selec
>  Show object IDs for all non-symbolic references displayed in the
>  .Cm ref
>  view.
> +.It Cm s
> +Toggle display order of references between sort by name and sort by timestamp.
>  .It Cm /
>  Prompt for a search pattern and start searching for matching references.
>  The search pattern is an extended regular expression which is matched
> blob - 74c66761f4e9c5685b0a4c978e74ba94fe3579ca
> blob + deb6c22c2d7e0b2eb805d71560f1aff83c2315cc
> --- tog/tog.c
> +++ tog/tog.c
> @@ -129,11 +129,13 @@ static struct got_reflist_head tog_refs = TAILQ_HEAD_I
>  static struct got_reflist_object_id_map *tog_refs_idmap;
>  
>  static const struct got_error *
> -tog_load_refs(struct got_repository *repo)
> +tog_load_refs(struct got_repository *repo, int sort_by_date)
>  {
>  	const struct got_error *err;
>  
> -	err = got_ref_list(&tog_refs, repo, NULL, got_ref_cmp_by_name, NULL);
> +	err = got_ref_list(&tog_refs, repo, NULL, sort_by_date ?
> +	    got_ref_cmp_by_commit_timestamp_descending : got_ref_cmp_by_name,
> +	    repo);
>  	if (err)
>  		return err;
>  
> @@ -439,7 +441,7 @@ struct tog_ref_view_state {
>  	struct tog_reflist_entry *first_displayed_entry;
>  	struct tog_reflist_entry *last_displayed_entry;
>  	struct tog_reflist_entry *selected_entry;
> -	int nrefs, ndisplayed, selected, show_ids;
> +	int nrefs, ndisplayed, selected, show_ids, sort_by_date;
>  	struct got_repository *repo;
>  	struct tog_reflist_entry *matched_entry;
>  	struct tog_colors colors;
> @@ -2586,7 +2588,7 @@ input_log_view(struct tog_view **new_view, struct tog_
>  		if (err)
>  			return err;
>  		tog_free_refs();
> -		err = tog_load_refs(s->repo);
> +		err = tog_load_refs(s->repo, 0);
>  		if (err)
>  			return err;
>  		err = got_commit_graph_open(&s->thread_args.graph,
> @@ -2793,7 +2795,7 @@ cmd_log(int argc, char *argv[])
>  
>  	/* already loaded by tog_log_with_path()? */
>  	if (TAILQ_EMPTY(&tog_refs)) {
> -		error = tog_load_refs(repo);
> +		error = tog_load_refs(repo, 0);
>  		if (error)
>  			goto done;
>  	}
> @@ -3914,7 +3916,7 @@ cmd_diff(int argc, char *argv[])
>  	if (error)
>  		goto done;
>  
> -	error = tog_load_refs(repo);
> +	error = tog_load_refs(repo, 0);
>  	if (error)
>  		goto done;
>  
> @@ -4842,7 +4844,7 @@ cmd_blame(int argc, char *argv[])
>  	if (error)
>  		goto done;
>  
> -	error = tog_load_refs(repo);
> +	error = tog_load_refs(repo, 0);
>  	if (error)
>  		goto done;
>  
> @@ -5695,7 +5697,7 @@ cmd_tree(int argc, char *argv[])
>  	if (error)
>  		goto done;
>  
> -	error = tog_load_refs(repo);
> +	error = tog_load_refs(repo, 0);
>  	if (error)
>  		goto done;
>  
> @@ -6230,6 +6232,15 @@ input_ref_view(struct tog_view **new_view, struct tog_
>  	case 'i':
>  		s->show_ids = !s->show_ids;
>  		break;
> +	case 's':
> +		s->sort_by_date = !s->sort_by_date;
> +		tog_free_refs();
> +		err = tog_load_refs(s->repo, s->sort_by_date);
> +		if (err)
> +			break;
> +		ref_view_free_refs(s);
> +		err = ref_view_load_refs(s);
> +		break;
>  	case KEY_ENTER:
>  	case '\r':
>  		if (!s->selected_entry)
> @@ -6326,7 +6337,7 @@ input_ref_view(struct tog_view **new_view, struct tog_
>  		break;
>  	case CTRL('l'):
>  		tog_free_refs();
> -		err = tog_load_refs(s->repo);
> +		err = tog_load_refs(s->repo, s->sort_by_date);
>  		if (err)
>  			break;
>  		ref_view_free_refs(s);
> @@ -6410,7 +6421,7 @@ cmd_ref(int argc, char *argv[])
>  	if (error)
>  		goto done;
>  
> -	error = tog_load_refs(repo);
> +	error = tog_load_refs(repo, 0);
>  	if (error)
>  		goto done;
>  
> @@ -6535,7 +6546,7 @@ tog_log_with_path(int argc, char *argv[])
>  	if (error)
>  		goto done;
>  
> -	error = tog_load_refs(repo);
> +	error = tog_load_refs(repo, 0);
>  	if (error)
>  		goto done;
>  	error = got_repo_match_object_id(&commit_id, NULL, worktree ?
> 
>