Skip to content

Commit ce11b80

Browse files
committed
Introduce helper to create symlinks that knows about index_state
On Windows, symbolic links actually have a type depending on the target: it can be a file or a directory. In certain circumstances, this poses problems, e.g. when a symbolic link is supposed to point into a submodule that is not checked out, so there is no way for Git to auto-detect the type. To help with that, we will add support over the course of the next commits to specify that symlink type via the Git attributes. This requires an index_state, though, something that Git for Windows' `symlink()` replacement cannot know about because the function signature is defined by the POSIX standard and not ours to change. So let's introduce a helper function to create symbolic links that *does* know about the index_state. Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent dacdc89 commit ce11b80

File tree

9 files changed

+21
-9
lines changed

9 files changed

+21
-9
lines changed

Diff for: apply.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -4395,7 +4395,7 @@ static int try_create_file(struct apply_state *state, const char *path,
43954395
/* Although buf:size is counted string, it also is NUL
43964396
* terminated.
43974397
*/
4398-
return !!symlink(buf, path);
4398+
return !!create_symlink(state && state->repo ? state->repo->index : NULL, buf, path);
43994399

44004400
fd = open(path, O_CREAT | O_EXCL | O_WRONLY, (mode & 0100) ? 0777 : 0666);
44014401
if (fd < 0)

Diff for: builtin/difftool.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
529529
}
530530
add_path(&wtdir, wtdir_len, dst_path);
531531
if (symlinks) {
532-
if (symlink(wtdir.buf, rdir.buf)) {
532+
if (create_symlink(lstate.istate, wtdir.buf, rdir.buf)) {
533533
ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
534534
goto finish;
535535
}

Diff for: compat/mingw.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3179,7 +3179,7 @@ int link(const char *oldpath, const char *newpath)
31793179
return 0;
31803180
}
31813181

3182-
int symlink(const char *target, const char *link)
3182+
int mingw_create_symlink(struct index_state *index, const char *target, const char *link)
31833183
{
31843184
wchar_t wtarget[MAX_LONG_PATH], wlink[MAX_LONG_PATH];
31853185
int len;

Diff for: compat/mingw.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,10 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
218218
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
219219
int link(const char *oldpath, const char *newpath);
220220
int uname(struct utsname *buf);
221-
int symlink(const char *target, const char *link);
222221
int readlink(const char *path, char *buf, size_t bufsiz);
222+
struct index_state;
223+
int mingw_create_symlink(struct index_state *index, const char *target, const char *link);
224+
#define create_symlink mingw_create_symlink
223225

224226
/*
225227
* replacements of existing functions

Diff for: entry.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
322322
if (!has_symlinks || to_tempfile)
323323
goto write_file_entry;
324324

325-
ret = symlink(new_blob, path);
325+
ret = create_symlink(state->istate, new_blob, path);
326326
free(new_blob);
327327
if (ret)
328328
return error_errno("unable to create symlink %s", path);

Diff for: git-compat-util.h

+10
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,16 @@ static inline int git_has_dir_sep(const char *path)
651651
#define is_mount_point is_mount_point_via_stat
652652
#endif
653653

654+
#ifndef create_symlink
655+
struct index_state;
656+
static inline int git_create_symlink(struct index_state *index UNUSED,
657+
const char *target, const char *link)
658+
{
659+
return symlink(target, link);
660+
}
661+
#define create_symlink git_create_symlink
662+
#endif
663+
654664
#ifndef query_user_email
655665
#define query_user_email() NULL
656666
#endif

Diff for: merge-recursive.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,7 @@ static int update_file_flags(struct merge_options *opt,
10051005
char *lnk = xmemdupz(buf, size);
10061006
safe_create_leading_directories_const(path);
10071007
unlink(path);
1008-
if (symlink(lnk, path))
1008+
if (create_symlink(&opt->priv->orig_index, lnk, path))
10091009
ret = err(opt, _("failed to symlink '%s': %s"),
10101010
path, strerror(errno));
10111011
free(lnk);

Diff for: refs/files-backend.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2044,7 +2044,7 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)
20442044

20452045
char *ref_path = get_locked_file_path(&lock->lk);
20462046
unlink(ref_path);
2047-
ret = symlink(target, ref_path);
2047+
ret = create_symlink(NULL, target, ref_path);
20482048
free(ref_path);
20492049

20502050
if (ret)

Diff for: setup.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -2135,7 +2135,7 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
21352135
if (strbuf_readlink(&lnk, template_path->buf,
21362136
st_template.st_size) < 0)
21372137
die_errno(_("cannot readlink '%s'"), template_path->buf);
2138-
if (symlink(lnk.buf, path->buf))
2138+
if (create_symlink(NULL, lnk.buf, path->buf))
21392139
die_errno(_("cannot symlink '%s' '%s'"),
21402140
lnk.buf, path->buf);
21412141
strbuf_release(&lnk);
@@ -2396,7 +2396,7 @@ static int create_default_files(const char *template_path,
23962396
path = git_path_buf(&buf, "tXXXXXX");
23972397
if (!close(xmkstemp(path)) &&
23982398
!unlink(path) &&
2399-
!symlink("testing", path) &&
2399+
!create_symlink(NULL, "testing", path) &&
24002400
!lstat(path, &st1) &&
24012401
S_ISLNK(st1.st_mode))
24022402
unlink(path); /* good */

0 commit comments

Comments
 (0)