commit - f3b2b5525998f769dba67674168f3ffb3cc495e5
commit + 437adc9d5be73b4b89441362ec89de754374a5a6
blob - 04443aa094268bbea1d505ec47ffe7bac202ab71
blob + 5796af500a49c702c5c1d95f32551f881ad0f9b5
--- lib/fileindex.c
+++ lib/fileindex.c
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 update_timestamps)
+ 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)
blob - f10058320f24affa0531641620b65ac3641a9b6f
blob + 537374d719e84293f1b449465ab63e092b44a20a
--- lib/got_lib_fileindex.h
+++ lib/got_lib_fileindex.h
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 *);
blob - 067bac22c55a94684a7dcb779417671747de7972
blob + 651bcc8f757194fa0d5259093255234ac99ee09d
--- lib/got_lib_worktree.h
+++ lib/got_lib_worktree.h
struct got_worktree {
char *root_path;
char *repo_path;
+ int root_fd;
char *path_prefix;
struct got_object_id *base_commit_id;
char *head_ref_name;
blob - 971955fbafa7d712d0e5a61dfe60def65321b0f0
blob + 91a87ba60ac2ebc61140d6778df16fc1e2f39016
--- lib/worktree.c
+++ lib/worktree.c
err = got_gotconfig_read(&(*worktree)->gotconfig,
(*worktree)->gotconfig_path);
+
+ (*worktree)->root_fd = open((*worktree)->root_path, O_DIRECTORY);
+ if ((*worktree)->root_fd == -1) {
+ err = got_error_from_errno2("open", (*worktree)->root_path);
+ goto done;
+ }
done:
if (repo)
got_repo_close(repo);
free(worktree->gotconfig_path);
got_gotconfig_free(worktree->gotconfig);
free(worktree);
+ close(worktree->root_fd);
return err;
}
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)
{
const struct got_error *err = NULL;
struct got_fileindex_entry *new_ie;
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;
* 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;
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,
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;
}
}
* 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;
goto done;
if (ie) {
- err = got_fileindex_entry_update(ie, ondisk_path,
- blob->id.sha1, worktree->base_commit_id->sha1, 1);
+ 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)
* 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,
- 0);
+ 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);
if (err)
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;
err = got_fileindex_entry_alloc(&ie, path2);
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, path2, NULL, NULL, 1);
if (err) {
got_fileindex_entry_free(ie);
goto done;
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;
if (status == GOT_STATUS_DELETE ||
status == GOT_STATUS_MODE_CHANGE) {
err = got_fileindex_entry_update(ie,
- ondisk_path, blob->id.sha1,
+ a->worktree->root_fd, relpath,
+ blob->id.sha1,
a->worktree->base_commit_id->sha1, 1);
if (err)
goto done;
}
static const struct got_error *
-update_fileindex_after_commit(struct got_pathlist_head *commitable_paths,
- struct got_object_id *new_base_commit_id, struct got_fileindex *fileindex,
- int have_staged_files)
+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) {
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,
+ 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,
+ 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,
- ct->blob_id->sha1, new_base_commit_id->sha1, 1);
+ 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);
+ relpath = NULL;
}
+done:
+ free(relpath);
return err;
}
if (err)
goto done;
- err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
- fileindex, have_staged_files);
+ 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)
err = sync_err;
if (err)
goto done;
- err = update_fileindex_after_commit(&commitable_paths, *new_commit_id,
- fileindex, 0);
+ 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)
err = sync_err;