Skip to content

Commit a0be62c

Browse files
jherlandgitster
authored andcommitted
notes-merge: use opendir/readdir instead of using read_directory()
notes_merge_commit() only needs to list all entries (non-recursively) under a directory, which can be easily accomplished with opendir/readdir and would be more lightweight than read_directory(). read_directory() is designed to list paths inside a working directory. Using it outside of its scope may lead to undesired effects. Apparently, one of the undesired effects of read_directory() is that it doesn't deal with being given absolute paths. This creates problems for notes_merge_commit() when git_path() returns an absolute path, which happens when the current working directory is in a subdirectory of the .git directory. Originally-by: Nguyễn Thái Ngọc Duy <[email protected]> Updated-by: Johan Herland <[email protected]> Signed-off-by: Johan Herland <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 01bfec8 commit a0be62c

File tree

2 files changed

+31
-21
lines changed

2 files changed

+31
-21
lines changed

notes-merge.c

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -687,51 +687,60 @@ int notes_merge_commit(struct notes_merge_options *o,
687687
{
688688
/*
689689
* Iterate through files in .git/NOTES_MERGE_WORKTREE and add all
690-
* found notes to 'partial_tree'. Write the updates notes tree to
690+
* found notes to 'partial_tree'. Write the updated notes tree to
691691
* the DB, and commit the resulting tree object while reusing the
692692
* commit message and parents from 'partial_commit'.
693693
* Finally store the new commit object SHA1 into 'result_sha1'.
694694
*/
695-
struct dir_struct dir;
696-
char *path = xstrdup(git_path(NOTES_MERGE_WORKTREE "/"));
697-
int path_len = strlen(path), i;
695+
DIR *dir;
696+
struct dirent *e;
697+
struct strbuf path = STRBUF_INIT;
698698
char *msg = strstr(partial_commit->buffer, "\n\n");
699699
struct strbuf sb_msg = STRBUF_INIT;
700+
int baselen;
700701

702+
strbuf_addstr(&path, git_path(NOTES_MERGE_WORKTREE));
701703
if (o->verbosity >= 3)
702-
printf("Committing notes in notes merge worktree at %.*s\n",
703-
path_len - 1, path);
704+
printf("Committing notes in notes merge worktree at %s\n",
705+
path.buf);
704706

705707
if (!msg || msg[2] == '\0')
706708
die("partial notes commit has empty message");
707709
msg += 2;
708710

709-
memset(&dir, 0, sizeof(dir));
710-
read_directory(&dir, path, path_len, NULL);
711-
for (i = 0; i < dir.nr; i++) {
712-
struct dir_entry *ent = dir.entries[i];
711+
dir = opendir(path.buf);
712+
if (!dir)
713+
die_errno("could not open %s", path.buf);
714+
715+
strbuf_addch(&path, '/');
716+
baselen = path.len;
717+
while ((e = readdir(dir)) != NULL) {
713718
struct stat st;
714-
const char *relpath = ent->name + path_len;
715719
unsigned char obj_sha1[20], blob_sha1[20];
716720

717-
if (ent->len - path_len != 40 || get_sha1_hex(relpath, obj_sha1)) {
721+
if (is_dot_or_dotdot(e->d_name))
722+
continue;
723+
724+
if (strlen(e->d_name) != 40 || get_sha1_hex(e->d_name, obj_sha1)) {
718725
if (o->verbosity >= 3)
719-
printf("Skipping non-SHA1 entry '%s'\n",
720-
ent->name);
726+
printf("Skipping non-SHA1 entry '%s%s'\n",
727+
path.buf, e->d_name);
721728
continue;
722729
}
723730

731+
strbuf_addstr(&path, e->d_name);
724732
/* write file as blob, and add to partial_tree */
725-
if (stat(ent->name, &st))
726-
die_errno("Failed to stat '%s'", ent->name);
727-
if (index_path(blob_sha1, ent->name, &st, HASH_WRITE_OBJECT))
728-
die("Failed to write blob object from '%s'", ent->name);
733+
if (stat(path.buf, &st))
734+
die_errno("Failed to stat '%s'", path.buf);
735+
if (index_path(blob_sha1, path.buf, &st, HASH_WRITE_OBJECT))
736+
die("Failed to write blob object from '%s'", path.buf);
729737
if (add_note(partial_tree, obj_sha1, blob_sha1, NULL))
730738
die("Failed to add resolved note '%s' to notes tree",
731-
ent->name);
739+
path.buf);
732740
if (o->verbosity >= 4)
733741
printf("Added resolved note for object %s: %s\n",
734742
sha1_to_hex(obj_sha1), sha1_to_hex(blob_sha1));
743+
strbuf_setlen(&path, baselen);
735744
}
736745

737746
strbuf_attach(&sb_msg, msg, strlen(msg), strlen(msg) + 1);
@@ -740,7 +749,8 @@ int notes_merge_commit(struct notes_merge_options *o,
740749
if (o->verbosity >= 4)
741750
printf("Finalized notes merge commit: %s\n",
742751
sha1_to_hex(result_sha1));
743-
free(path);
752+
strbuf_release(&path);
753+
closedir(dir);
744754
return 0;
745755
}
746756

t/t3310-notes-merge-manual-resolve.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ foo
558558
bar
559559
EOF
560560

561-
test_expect_failure 'switch cwd before committing notes merge' '
561+
test_expect_success 'switch cwd before committing notes merge' '
562562
git notes add -m foo HEAD &&
563563
git notes --ref=other add -m bar HEAD &&
564564
test_must_fail git notes merge refs/notes/other &&

0 commit comments

Comments
 (0)