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

From:
Stefan Sperling <stsp@stsp.name>
Subject:
Re: change got_worktree_init, open_worktree to use fds
To:
Yang Zhong <yzhong@freebsdfoundation.org>
Cc:
gameoftrees@openbsd.org
Date:
Tue, 8 Dec 2020 21:49:00 +0100

Download raw body.

Thread
On Tue, Dec 08, 2020 at 10:31:25AM -0800, Yang Zhong wrote:
> Here's a small patch demonstrating the use of the new fd field in
> got_worktree. I modified got_fileindex_entry_update to take in an
> fd, which required all of its calls to be modified as well. As you
> said, fileindexes have their paths stored relative to the worktree's
> path already, so most of the time I can pass in a pre-existing
> relative path instead of the absolute one.
> 
> This required me to add worktree fd fields to a few helpers as well
> as got_fileindex_entry_update itself. There is also one spot where
> I used got_path_skip_common_ancestor to create a relative path, in
> update_fileindex_after_commit. I thought that ct->path would work
> (replacing ct->ondisk_path), but it did not; I'm probably missing
> some of the nuances in this case.

The problem with ct->path might be that collect_commitables() prepends
a slash to the relative path that was fetched from the file index.
I don't remember why this was done. Perhaps this could be changed,
but we can deal with that later.

This patch looks very good to me. I only have some style nits.

The size of this patch is well chosen for code review. I suppose it is
not very easy to extract individual changes like this from everything
you've already done for the proof of concept patch. Well done!

I see several overlong lines in this patch.
Please wrap lines at 80 columns, ideally a bit less than 80.

Indentation uses tabs for regular lines and 4 spaces for lines
that continue a statement.
Example from the OpenBSD style(9) man page:

		   z = a + really + long + statement + that + needs +
		       two + lines + gets + indented + four + spaces +
		       on + the + second + and + subsequent + lines;

More below:

> diff --git a/lib/fileindex.c b/lib/fileindex.c
> index b46dbb29..ce162817 100644
> --- a/lib/fileindex.c
> +++ b/lib/fileindex.c
> @@ -88,15 +88,15 @@ got_fileindex_perms_to_st(struct got_fileindex_entry *ie)
>  
>  const struct got_error *
>  got_fileindex_entry_update(struct got_fileindex_entry *ie,
> -    const char *ondisk_path, uint8_t *blob_sha1, uint8_t *commit_sha1,
> +    int wt_fd, const char *ondisk_path, uint8_t *blob_sha1, uint8_t *commit_sha1,
>      int update_timestamps)
>  {
>  	struct stat sb;
>  
> -	if (lstat(ondisk_path, &sb) != 0) {
> +	if (fstatat(wt_fd, ondisk_path, &sb, AT_SYMLINK_NOFOLLOW) != 0) {
>  		if (!((ie->flags & GOT_FILEIDX_F_NO_FILE_ON_DISK) &&
>  		    errno == ENOENT))
> -			return got_error_from_errno2("lstat", ondisk_path);
> +			return got_error_from_errno2("fstatat", ondisk_path);
>  		sb.st_mode = GOT_DEFAULT_FILE_MODE;
>  	} else {
>  		if (sb.st_mode & S_IFDIR)
> diff --git a/lib/got_lib_fileindex.h b/lib/got_lib_fileindex.h
> index f1005832..537374d7 100644
> --- a/lib/got_lib_fileindex.h
> +++ b/lib/got_lib_fileindex.h
> @@ -108,7 +108,7 @@ uint16_t got_fileindex_perms_from_st(struct stat *);
>  mode_t got_fileindex_perms_to_st(struct got_fileindex_entry *);
>  
>  const struct got_error *got_fileindex_entry_update(struct got_fileindex_entry *,
> -    const char *, uint8_t *, uint8_t *, int);
> +    int, const char *, uint8_t *, uint8_t *, int);
>  const struct got_error *got_fileindex_entry_alloc(struct got_fileindex_entry **,
>      const char *);
>  void got_fileindex_entry_free(struct got_fileindex_entry *);
> diff --git a/lib/worktree.c b/lib/worktree.c
> index 8bf4b7ff..8994bf43 100644
> --- a/lib/worktree.c
> +++ b/lib/worktree.c
> @@ -1175,7 +1175,7 @@ done:
>  static const struct got_error *
>  create_fileindex_entry(struct got_fileindex_entry **new_iep,
>      struct got_fileindex *fileindex, struct got_object_id *base_commit_id,
> -    const char *ondisk_path, const char *path, struct got_object_id *blob_id)
> +    int wt_fd, const char *path, struct got_object_id *blob_id)

The base_commit_id and wt_fd arguments fall out of struct worktree.

I can imagine naddy grinding his teeth at the sight of this and plotting
a plan to reduce the number of parameters by passing a 'struct worktree *'
instead as soon as you commit this change :)

>  {
>  	const struct got_error *err = NULL;
>  	struct got_fileindex_entry *new_ie;
> @@ -1186,7 +1186,7 @@ create_fileindex_entry(struct got_fileindex_entry **new_iep,
>  	if (err)
>  		return err;
>  
> -	err = got_fileindex_entry_update(new_ie, ondisk_path,
> +	err = got_fileindex_entry_update(new_ie, wt_fd, path,
>  	    blob_id->sha1, base_commit_id->sha1, 1);
>  	if (err)
>  		goto done;
> @@ -1861,11 +1861,11 @@ done:
>   * we had to run a full content comparison to find out.
>   */
>  static const struct got_error *
> -sync_timestamps(char *ondisk_path, unsigned char status,
> +sync_timestamps(int wt_fd, const char *path, unsigned char status,
>      struct got_fileindex_entry *ie, struct stat *sb)
>  {
>  	if (status == GOT_STATUS_NO_CHANGE && stat_info_differs(ie, sb))
> -		return got_fileindex_entry_update(ie, ondisk_path,
> +		return got_fileindex_entry_update(ie, wt_fd, path,
>  		    ie->blob_sha1, ie->commit_sha1, 1);
>  
>  	return NULL;
> @@ -1918,7 +1918,7 @@ update_blob(struct got_worktree *worktree,
>  		if (got_fileindex_entry_has_commit(ie) &&
>  		    memcmp(ie->commit_sha1, worktree->base_commit_id->sha1,
>  		    SHA1_DIGEST_LENGTH) == 0) {
> -			err = sync_timestamps(ondisk_path, status, ie, &sb);
> +			err = sync_timestamps(worktree->root_fd, path, status, ie, &sb);
>  			if (err)
>  				goto done;
>  			err = (*progress_cb)(progress_arg, GOT_STATUS_EXISTS,
> @@ -1928,7 +1928,7 @@ update_blob(struct got_worktree *worktree,
>  		if (got_fileindex_entry_has_blob(ie) &&
>  		    memcmp(ie->blob_sha1, te->id.sha1,
>  		    SHA1_DIGEST_LENGTH) == 0) {
> -			err = sync_timestamps(ondisk_path, status, ie, &sb);
> +			err = sync_timestamps(worktree->root_fd, path, status, ie, &sb);
>  			goto done;
>  		}
>  	}
> @@ -1987,17 +1987,17 @@ update_blob(struct got_worktree *worktree,
>  		 * Otherwise, a future status walk would treat them as
>  		 * unmodified files again.
>  		 */
> -		err = got_fileindex_entry_update(ie, ondisk_path,
> +		err = got_fileindex_entry_update(ie, worktree->root_fd, path,
>  		    blob->id.sha1, worktree->base_commit_id->sha1,
>  		    update_timestamps);
>  	} else if (status == GOT_STATUS_MODE_CHANGE) {
> -		err = got_fileindex_entry_update(ie, ondisk_path,
> +		err = got_fileindex_entry_update(ie, worktree->root_fd, path,
>  		    blob->id.sha1, worktree->base_commit_id->sha1, 0);
>  	} else if (status == GOT_STATUS_DELETE) {
>  		err = (*progress_cb)(progress_arg, GOT_STATUS_MERGE, path);
>  		if (err)
>  			goto done;
> -		err = got_fileindex_entry_update(ie, ondisk_path,
> +		err = got_fileindex_entry_update(ie, worktree->root_fd, path,
>  		    blob->id.sha1, worktree->base_commit_id->sha1, 0);
>  		if (err)
>  			goto done;
> @@ -2020,11 +2020,11 @@ update_blob(struct got_worktree *worktree,
>  			goto done;
>  
>  		if (ie) {
> -			err = got_fileindex_entry_update(ie, ondisk_path,
> +			err = got_fileindex_entry_update(ie, worktree->root_fd, path,
>  			    blob->id.sha1, worktree->base_commit_id->sha1, 1);
>  		} else {
>  			err = create_fileindex_entry(&ie, fileindex,
> -			    worktree->base_commit_id, ondisk_path, path,
> +			    worktree->base_commit_id, worktree->root_fd, path,
>  			    &blob->id);
>  		}
>  		if (err)
> @@ -2124,7 +2124,7 @@ delete_blob(struct got_worktree *worktree, struct got_fileindex *fileindex,
>  		 * Preserve the working file and change the deleted blob's
>  		 * entry into a schedule-add entry.
>  		 */
> -		err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL,
> +		err = got_fileindex_entry_update(ie, worktree->root_fd, ie->path, NULL, NULL,
>  		    0);
>  	} else {
>  		err = (*progress_cb)(progress_arg, GOT_STATUS_DELETE, ie->path);
> @@ -2933,7 +2933,7 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
>  				goto done;
>  			if (status == GOT_STATUS_DELETE) {
>  				err = got_fileindex_entry_update(ie,
> -				    ondisk_path, blob2->id.sha1,
> +				    a->worktree->root_fd, path2, blob2->id.sha1,
>  				    a->worktree->base_commit_id->sha1, 0);
>  				if (err)
>  					goto done;
> @@ -2955,7 +2955,7 @@ merge_file_cb(void *arg, struct got_blob_object *blob1,
>  			err = got_fileindex_entry_alloc(&ie, path2);
>  			if (err)
>  				goto done;
> -			err = got_fileindex_entry_update(ie, ondisk_path,
> +			err = got_fileindex_entry_update(ie, a->worktree->root_fd, path2,
>  			    NULL, NULL, 1);
>  			if (err) {
>  				got_fileindex_entry_free(ie);
> @@ -3775,7 +3775,7 @@ schedule_addition(void *arg, unsigned char status, unsigned char staged_status,
>  	err = got_fileindex_entry_alloc(&ie, relpath);
>  	if (err)
>  		goto done;
> -	err = got_fileindex_entry_update(ie, ondisk_path, NULL, NULL, 1);
> +	err = got_fileindex_entry_update(ie, a->worktree->root_fd, relpath, NULL, NULL, 1);
>  	if (err) {
>  		got_fileindex_entry_free(ie);
>  		goto done;
> @@ -4581,8 +4581,8 @@ revert_file(void *arg, unsigned char status, unsigned char staged_status,
>  				goto done;
>  			if (status == GOT_STATUS_DELETE ||
>  			    status == GOT_STATUS_MODE_CHANGE) {
> -				err = got_fileindex_entry_update(ie,
> -				    ondisk_path, blob->id.sha1,
> +				err = got_fileindex_entry_update(ie, a->worktree->root_fd,
> +				    relpath, blob->id.sha1,
>  				    a->worktree->base_commit_id->sha1, 1);
>  				if (err)
>  					goto done;
> @@ -5285,18 +5285,25 @@ done:
>  }
>  
>  static const struct got_error *
> -update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
> +update_fileindex_after_commit(struct got_worktree *worktree, struct got_pathlist_head *commitable_paths,
>      struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
>      int have_staged_files)
>  {
>  	const struct got_error *err = NULL;
>  	struct got_pathlist_entry *pe;
> +	char *relpath = NULL;
>  
>  	TAILQ_FOREACH(pe, commitable_paths, entry) {
>  		struct got_fileindex_entry *ie;
>  		struct got_commitable *ct = pe->data;
>  
>  		ie = got_fileindex_entry_get(fileindex, pe->path, pe->path_len);
> +
> +		err = got_path_skip_common_ancestor(&relpath,
> +		    worktree->root_path, ct->ondisk_path);
> +		if (err)
> +			goto done;
> +
>  		if (ie) {
>  			if (ct->status == GOT_STATUS_DELETE ||
>  			    ct->staged_status == GOT_STATUS_DELETE) {
> @@ -5306,32 +5313,38 @@ update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
>  				got_fileindex_entry_stage_set(ie,
>  				    GOT_FILEIDX_STAGE_NONE);
>  				got_fileindex_entry_staged_filetype_set(ie, 0);
> -				err = got_fileindex_entry_update(ie,
> -				    ct->ondisk_path, ct->staged_blob_id->sha1,
> +
> +				err = got_fileindex_entry_update(ie, worktree->root_fd,
> +				    relpath, ct->staged_blob_id->sha1,
>  				    new_base_commit_id->sha1,
>  				    !have_staged_files);
>  			} else
> -				err = got_fileindex_entry_update(ie,
> -				    ct->ondisk_path, ct->blob_id->sha1,
> +				err = got_fileindex_entry_update(ie, worktree->root_fd,
> +				    relpath, ct->blob_id->sha1,
>  				    new_base_commit_id->sha1,
>  				    !have_staged_files);
>  		} else {
>  			err = got_fileindex_entry_alloc(&ie, pe->path);
>  			if (err)
> -				break;
> -			err = got_fileindex_entry_update(ie, ct->ondisk_path,
> +				goto done;
> +			err = got_fileindex_entry_update(ie, worktree->root_fd, relpath,
>  			    ct->blob_id->sha1, new_base_commit_id->sha1, 1);
>  			if (err) {
>  				got_fileindex_entry_free(ie);
> -				break;
> +				goto done;
>  			}
>  			err = got_fileindex_entry_add(fileindex, ie);
>  			if (err) {
>  				got_fileindex_entry_free(ie);
> -				break;
> +				goto done;
>  			}
>  		}
> +		free(relpath); //NOTE add done

Hmm. I don't understand what this comment is trying to tell me.

Style nit: no C++-style comments please, simply because it goes
against the OpenBSD style(9) rules. (I don't really care about comment
style myself; I just want to avoid having to sweep the code base for
stuff like this in the event that Got gets imported into the OpenBSD
base system some day...)

> +		relpath = NULL;
>  	}
> +done:
> +	if (relpath)
> +		free(relpath);
>  	return err;
>  }
>  
> @@ -5662,7 +5675,7 @@ got_worktree_commit(struct got_object_id **new_commit_id,
>  	if (err)
>  		goto done;
>  
> -	err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
> +	err = update_fileindex_after_commit(worktree, &commitable_paths, *new_commit_id,
>  	    fileindex, have_staged_files);
>  	sync_err = sync_fileindex(fileindex, fileindex_path);
>  	if (sync_err && err == NULL)
> @@ -6248,7 +6261,7 @@ rebase_commit(struct got_object_id **new_commit_id,
>  	if (err)
>  		goto done;
>  
> -	err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
> +	err = update_fileindex_after_commit(worktree, &commitable_paths, *new_commit_id,
>  	    fileindex, 0);
>  	sync_err = sync_fileindex(fileindex, fileindex_path);
>  	if (sync_err && err == NULL)