Skip to content

Commit 6b1cfbc

Browse files
dschoGit for Windows Build Agent
authored andcommitted
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 <[email protected]>
1 parent 1517277 commit 6b1cfbc

File tree

8 files changed

+20
-8
lines changed

8 files changed

+20
-8
lines changed

apply.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4401,7 +4401,7 @@ static int try_create_file(struct apply_state *state, const char *path,
44014401
/* Although buf:size is counted string, it also is NUL
44024402
* terminated.
44034403
*/
4404-
return !!symlink(buf, path);
4404+
return !!create_symlink(state && state->repo ? state->repo->index : NULL, buf, path);
44054405

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

builtin/difftool.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ static int run_dir_diff(struct repository *repo,
544544
}
545545
add_path(&wtdir, wtdir_len, dst_path);
546546
if (dt_options->symlinks) {
547-
if (symlink(wtdir.buf, rdir.buf)) {
547+
if (create_symlink(lstate.istate, wtdir.buf, rdir.buf)) {
548548
ret = error_errno("could not symlink '%s' to '%s'", wtdir.buf, rdir.buf);
549549
goto finish;
550550
}

compat/mingw-posix.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,8 +193,10 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
193193
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
194194
int link(const char *oldpath, const char *newpath);
195195
int uname(struct utsname *buf);
196-
int symlink(const char *target, const char *link);
197196
int readlink(const char *path, char *buf, size_t bufsiz);
197+
struct index_state;
198+
int mingw_create_symlink(struct index_state *index, const char *target, const char *link);
199+
#define create_symlink mingw_create_symlink
198200

199201
/*
200202
* replacements of existing functions

compat/mingw.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3156,7 +3156,7 @@ int link(const char *oldpath, const char *newpath)
31563156
return 0;
31573157
}
31583158

3159-
int symlink(const char *target, const char *link)
3159+
int mingw_create_symlink(struct index_state *index UNUSED, const char *target, const char *link)
31603160
{
31613161
wchar_t wtarget[MAX_LONG_PATH], wlink[MAX_LONG_PATH];
31623162
int len;

entry.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ static int write_entry(struct cache_entry *ce, char *path, struct conv_attrs *ca
324324
if (!has_symlinks || to_tempfile)
325325
goto write_file_entry;
326326

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

git-compat-util.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,16 @@ static inline int git_has_dir_sep(const char *path)
396396
#define is_mount_point is_mount_point_via_stat
397397
#endif
398398

399+
#ifndef create_symlink
400+
struct index_state;
401+
static inline int git_create_symlink(struct index_state *index UNUSED,
402+
const char *target, const char *link)
403+
{
404+
return symlink(target, link);
405+
}
406+
#define create_symlink git_create_symlink
407+
#endif
408+
399409
#ifndef query_user_email
400410
#define query_user_email() NULL
401411
#endif

refs/files-backend.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2053,7 +2053,7 @@ static int create_ref_symlink(struct ref_lock *lock, const char *target)
20532053

20542054
char *ref_path = get_locked_file_path(&lock->lk);
20552055
unlink(ref_path);
2056-
ret = symlink(target, ref_path);
2056+
ret = create_symlink(NULL, target, ref_path);
20572057
free(ref_path);
20582058

20592059
if (ret)

setup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2141,7 +2141,7 @@ static void copy_templates_1(struct strbuf *path, struct strbuf *template_path,
21412141
if (strbuf_readlink(&lnk, template_path->buf,
21422142
st_template.st_size) < 0)
21432143
die_errno(_("cannot readlink '%s'"), template_path->buf);
2144-
if (symlink(lnk.buf, path->buf))
2144+
if (create_symlink(NULL, lnk.buf, path->buf))
21452145
die_errno(_("cannot symlink '%s' '%s'"),
21462146
lnk.buf, path->buf);
21472147
strbuf_release(&lnk);
@@ -2402,7 +2402,7 @@ static int create_default_files(const char *template_path,
24022402
repo_git_path_replace(the_repository, &path, "tXXXXXX");
24032403
if (!close(xmkstemp(path.buf)) &&
24042404
!unlink(path.buf) &&
2405-
!symlink("testing", path.buf) &&
2405+
!create_symlink(NULL, "testing", path.buf) &&
24062406
!lstat(path.buf, &st1) &&
24072407
S_ISLNK(st1.st_mode))
24082408
unlink(path.buf); /* good */

0 commit comments

Comments
 (0)