Skip to content

Commit de53194

Browse files
committed
Merge pull request #156 from kblees/kb/symlinks
Symlink support
2 parents 3fdd7e1 + c10f0f8 commit de53194

File tree

10 files changed

+526
-204
lines changed

10 files changed

+526
-204
lines changed

compat/mingw.c

Lines changed: 490 additions & 173 deletions
Large diffs are not rendered by default.

compat/mingw.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,6 @@ struct utsname {
123123
* trivial stubs
124124
*/
125125

126-
static inline int readlink(const char *path, char *buf, size_t bufsiz)
127-
{ errno = ENOSYS; return -1; }
128-
static inline int symlink(const char *oldpath, const char *newpath)
129-
{ errno = ENOSYS; return -1; }
130126
static inline int fchmod(int fildes, mode_t mode)
131127
{ errno = ENOSYS; return -1; }
132128
#ifndef __MINGW64_VERSION_MAJOR
@@ -218,6 +214,8 @@ int setitimer(int type, struct itimerval *in, struct itimerval *out);
218214
int sigaction(int sig, struct sigaction *in, struct sigaction *out);
219215
int link(const char *oldpath, const char *newpath);
220216
int uname(struct utsname *buf);
217+
int symlink(const char *target, const char *link);
218+
int readlink(const char *path, char *buf, size_t bufsiz);
221219

222220
/*
223221
* replacements of existing functions
@@ -447,6 +445,8 @@ static inline void convert_slashes(char *path)
447445
int mingw_offset_1st_component(const char *path);
448446
#define offset_1st_component mingw_offset_1st_component
449447
#define PATH_SEP ';'
448+
extern char *mingw_query_user_email(void);
449+
#define query_user_email mingw_query_user_email
450450
#if !defined(__MINGW64_VERSION_MAJOR) && (!defined(_MSC_VER) || _MSC_VER < 1800)
451451
#define PRIuMAX "I64u"
452452
#define PRId64 "I64d"

compat/win32.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@
66
#include <windows.h>
77
#endif
88

9-
static inline int file_attr_to_st_mode (DWORD attr)
9+
static inline int file_attr_to_st_mode (DWORD attr, DWORD tag)
1010
{
1111
int fMode = S_IREAD;
12-
if (attr & FILE_ATTRIBUTE_DIRECTORY)
12+
if ((attr & FILE_ATTRIBUTE_REPARSE_POINT) && tag == IO_REPARSE_TAG_SYMLINK)
13+
fMode |= S_IFLNK;
14+
else if (attr & FILE_ATTRIBUTE_DIRECTORY)
1315
fMode |= S_IFDIR;
1416
else
1517
fMode |= S_IFREG;

compat/win32/dirent.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ static inline void finddata2dirent(struct dirent *ent, WIN32_FIND_DATAW *fdata)
1616
xwcstoutf(ent->d_name, fdata->cFileName, MAX_PATH * 3);
1717

1818
/* Set file type, based on WIN32_FIND_DATA */
19-
if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
19+
if ((fdata->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
20+
&& fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK)
21+
ent->d_type = DT_LNK;
22+
else if (fdata->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
2023
ent->d_type = DT_DIR;
2124
else
2225
ent->d_type = DT_REG;

compat/win32/fscache.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,9 +149,10 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
149149

150150
fse = fsentry_alloc(list, buf, len);
151151

152-
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes);
153-
fse->st_size = (((off64_t) (fdata->nFileSizeHigh)) << 32)
154-
| fdata->nFileSizeLow;
152+
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes,
153+
fdata->dwReserved0);
154+
fse->st_size = S_ISLNK(fse->st_mode) ? MAX_LONG_PATH :
155+
fdata->nFileSizeLow | (((off_t) fdata->nFileSizeHigh) << 32);
155156
fse->st_atime = filetime_to_time_t(&(fdata->ftLastAccessTime));
156157
fse->st_mtime = filetime_to_time_t(&(fdata->ftLastWriteTime));
157158
fse->st_ctime = filetime_to_time_t(&(fdata->ftCreationTime));
@@ -442,7 +443,8 @@ static struct dirent *fscache_readdir(DIR *base_dir)
442443
if (!next)
443444
return NULL;
444445
dir->pfsentry = next;
445-
dir->dirent.d_type = S_ISDIR(next->st_mode) ? DT_DIR : DT_REG;
446+
dir->dirent.d_type = S_ISREG(next->st_mode) ? DT_REG :
447+
S_ISDIR(next->st_mode) ? DT_DIR : DT_LNK;
446448
dir->dirent.d_name = (char*) next->name;
447449
return &(dir->dirent);
448450
}

compat/winansi.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <wingdi.h>
88
#include <winreg.h>
99
#include "win32.h"
10+
#include "win32/lazyload.h"
1011

1112
static int fd_is_interactive[3] = { 0, 0, 0 };
1213
#define FD_CONSOLE 0x1
@@ -41,26 +42,21 @@ typedef struct _CONSOLE_FONT_INFOEX {
4142
#endif
4243
#endif
4344

44-
typedef BOOL (WINAPI *PGETCURRENTCONSOLEFONTEX)(HANDLE, BOOL,
45-
PCONSOLE_FONT_INFOEX);
46-
4745
static void warn_if_raster_font(void)
4846
{
4947
DWORD fontFamily = 0;
50-
PGETCURRENTCONSOLEFONTEX pGetCurrentConsoleFontEx;
48+
DECLARE_PROC_ADDR(kernel32.dll, BOOL, GetCurrentConsoleFontEx,
49+
HANDLE, BOOL, PCONSOLE_FONT_INFOEX);
5150

5251
/* don't bother if output was ascii only */
5352
if (!non_ascii_used)
5453
return;
5554

5655
/* GetCurrentConsoleFontEx is available since Vista */
57-
pGetCurrentConsoleFontEx = (PGETCURRENTCONSOLEFONTEX) GetProcAddress(
58-
GetModuleHandle("kernel32.dll"),
59-
"GetCurrentConsoleFontEx");
60-
if (pGetCurrentConsoleFontEx) {
56+
if (INIT_PROC_ADDR(GetCurrentConsoleFontEx)) {
6157
CONSOLE_FONT_INFOEX cfi;
6258
cfi.cbSize = sizeof(cfi);
63-
if (pGetCurrentConsoleFontEx(console, 0, &cfi))
59+
if (GetCurrentConsoleFontEx(console, 0, &cfi))
6460
fontFamily = cfi.FontFamily;
6561
} else {
6662
/* pre-Vista: check default console font in registry */

git-compat-util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,10 @@ static inline char *git_find_last_dir_sep(const char *path)
388388
#define find_last_dir_sep git_find_last_dir_sep
389389
#endif
390390

391+
#ifndef query_user_email
392+
#define query_user_email() NULL
393+
#endif
394+
391395
#if defined(__HP_cc) && (__HP_cc >= 61000)
392396
#define NORETURN __attribute__((noreturn))
393397
#define NORETURN_PTR

ident.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,9 @@ const char *ident_default_email(void)
168168
strbuf_addstr(&git_default_email, email);
169169
committer_ident_explicitly_given |= IDENT_MAIL_GIVEN;
170170
author_ident_explicitly_given |= IDENT_MAIL_GIVEN;
171+
} else if ((email = query_user_email()) && email[0]) {
172+
strbuf_addstr(&git_default_email, email);
173+
free((char *)email);
171174
} else
172175
copy_email(xgetpwuid_self(&default_email_is_bogus),
173176
&git_default_email, &default_email_is_bogus);

lockfile.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,14 @@ static void trim_last_path_component(struct strbuf *path)
1717
int i = path->len;
1818

1919
/* back up past trailing slashes, if any */
20-
while (i && path->buf[i - 1] == '/')
20+
while (i && is_dir_sep(path->buf[i - 1]))
2121
i--;
2222

2323
/*
2424
* then go backwards until a slash, or the beginning of the
2525
* string
2626
*/
27-
while (i && path->buf[i - 1] != '/')
27+
while (i && !is_dir_sep(path->buf[i - 1]))
2828
i--;
2929

3030
strbuf_setlen(path, i);

strbuf.c

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,30 +426,25 @@ ssize_t strbuf_write(struct strbuf *sb, FILE *f)
426426
}
427427

428428

429-
#define STRBUF_MAXLINK (2*PATH_MAX)
430-
431429
int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
432430
{
433431
size_t oldalloc = sb->alloc;
434432

435433
if (hint < 32)
436434
hint = 32;
437435

438-
while (hint < STRBUF_MAXLINK) {
436+
for (;; hint *= 2) {
439437
int len;
440438

441-
strbuf_grow(sb, hint);
442-
len = readlink(path, sb->buf, hint);
439+
strbuf_grow(sb, hint + 1);
440+
len = readlink(path, sb->buf, hint + 1);
443441
if (len < 0) {
444442
if (errno != ERANGE)
445443
break;
446-
} else if (len < hint) {
444+
} else if (len <= hint) {
447445
strbuf_setlen(sb, len);
448446
return 0;
449447
}
450-
451-
/* .. the buffer was too small - try again */
452-
hint *= 2;
453448
}
454449
if (oldalloc == 0)
455450
strbuf_release(sb);

0 commit comments

Comments
 (0)