Skip to content

Commit b1735b1

Browse files
Clemens Buchachergitster
authored andcommitted
do not overwrite files in leading path
If the work tree contains an untracked file x, and unpack-trees wants to checkout a path x/*, the file x is removed unconditionally. Instead, apply the same checks that are normally used for untracked files, and abort if the file cannot be removed. Signed-off-by: Clemens Buchacher <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f7e3bd3 commit b1735b1

File tree

4 files changed

+31
-10
lines changed

4 files changed

+31
-10
lines changed

cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -859,7 +859,7 @@ struct cache_def {
859859

860860
extern int has_symlink_leading_path(const char *name, int len);
861861
extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
862-
extern int has_symlink_or_noent_leading_path(const char *name, int len);
862+
extern int check_leading_path(const char *name, int len);
863863
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
864864
extern void schedule_dir_for_removal(const char *name, int len);
865865
extern void remove_scheduled_dirs(void);

symlinks.c

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,15 +209,26 @@ int has_symlink_leading_path(const char *name, int len)
209209
}
210210

211211
/*
212-
* Return non-zero if path 'name' has a leading symlink component or
212+
* Return zero if path 'name' has a leading symlink component or
213213
* if some leading path component does not exists.
214+
*
215+
* Return -1 if leading path exists and is a directory.
216+
*
217+
* Return path length if leading path exists and is neither a
218+
* directory nor a symlink.
214219
*/
215-
int has_symlink_or_noent_leading_path(const char *name, int len)
220+
int check_leading_path(const char *name, int len)
216221
{
217222
struct cache_def *cache = &default_cache; /* FIXME */
218-
return lstat_cache(cache, name, len,
219-
FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT) &
220-
(FL_SYMLINK|FL_NOENT);
223+
int flags;
224+
int match_len = lstat_cache_matchlen(cache, name, len, &flags,
225+
FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
226+
if (flags & (FL_SYMLINK|FL_NOENT))
227+
return 0;
228+
else if (flags & FL_DIR)
229+
return -1;
230+
else
231+
return match_len;
221232
}
222233

223234
/*

t/t7607-merge-overwrite.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ test_expect_success 'will not overwrite untracked subtree' '
100100
test_cmp important sub/f/important
101101
'
102102

103-
test_expect_failure 'will not overwrite untracked file in leading path' '
103+
test_expect_success 'will not overwrite untracked file in leading path' '
104104
git reset --hard c0 &&
105105
rm -rf sub &&
106106
cp important sub &&

unpack-trees.c

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ static void display_error_msgs(struct unpack_trees_options *o)
182182
*/
183183
static void unlink_entry(struct cache_entry *ce)
184184
{
185-
if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
185+
if (!check_leading_path(ce->name, ce_namelen(ce)))
186186
return;
187187
if (remove_or_warn(ce->ce_mode, ce->name))
188188
return;
@@ -1194,18 +1194,28 @@ static int verify_absent_1(struct cache_entry *ce,
11941194
enum unpack_trees_error_types error_type,
11951195
struct unpack_trees_options *o)
11961196
{
1197+
int len;
11971198
struct stat st;
11981199

11991200
if (o->index_only || o->reset || !o->update)
12001201
return 0;
12011202

1202-
if (has_symlink_or_noent_leading_path(ce->name, ce_namelen(ce)))
1203+
len = check_leading_path(ce->name, ce_namelen(ce));
1204+
if (!len)
12031205
return 0;
1206+
else if (len > 0) {
1207+
char path[PATH_MAX + 1];
1208+
memcpy(path, ce->name, len);
1209+
path[len] = 0;
1210+
lstat(path, &st);
12041211

1205-
if (!lstat(ce->name, &st))
1212+
return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st,
1213+
error_type, o);
1214+
} else if (!lstat(ce->name, &st))
12061215
return check_ok_to_remove(ce->name, ce_namelen(ce),
12071216
ce_to_dtype(ce), ce, &st,
12081217
error_type, o);
1218+
12091219
return 0;
12101220
}
12111221

0 commit comments

Comments
 (0)