Skip to content

Commit da65d42

Browse files
dschoderrickstolee
authored andcommitted
Merge pull request git-for-windows#366 from dscho/features/scalar-2.32.0
Integrate Scalar (ported to C) into vfs-2.32.0
2 parents 7271479 + ae795fd commit da65d42

File tree

20 files changed

+2830
-30
lines changed

20 files changed

+2830
-30
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on: [push, pull_request]
44

55
env:
66
DEVELOPER: 1
7+
INCLUDE_SCALAR: YesPlease
78

89
jobs:
910
ci-config:

Documentation/config/core.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,3 +726,12 @@ core.abbrev::
726726
If set to "no", no abbreviation is made and the object names
727727
are shown in their full length.
728728
The minimum length is 4.
729+
730+
core.configWriteLockTimeoutMS::
731+
When processes try to write to the config concurrently, it is likely
732+
that one process "wins" and the other process(es) fail to lock the
733+
config file. By configuring a timeout larger than zero, Git can be
734+
told to try to lock the config again a couple times within the
735+
specified timeout. If the timeout is configure to zero (which is the
736+
default), Git will fail immediately when the config is already
737+
locked.

Makefile

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1986,6 +1986,10 @@ ifndef PAGER_ENV
19861986
PAGER_ENV = LESS=FRX LV=-c
19871987
endif
19881988

1989+
ifneq (,$(INCLUDE_SCALAR))
1990+
EXTRA_PROGRAMS += contrib/scalar/scalar$X
1991+
endif
1992+
19891993
QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir
19901994
QUIET_SUBDIR1 =
19911995

@@ -2499,6 +2503,10 @@ endif
24992503
.PHONY: objects
25002504
objects: $(OBJECTS)
25012505

2506+
SCALAR_SOURCES := contrib/scalar/scalar.c contrib/scalar/json-parser.c
2507+
SCALAR_OBJECTS := $(SCALAR_SOURCES:c=o)
2508+
OBJECTS += $(SCALAR_OBJECTS)
2509+
25022510
dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d)
25032511
dep_dirs := $(addsuffix .depend,$(sort $(dir $(OBJECTS))))
25042512

@@ -2644,6 +2652,13 @@ $(REMOTE_CURL_PRIMARY): remote-curl.o http.o http-walker.o GIT-LDFLAGS $(GITLIBS
26442652
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
26452653
$(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS)
26462654

2655+
contrib/scalar/scalar$X: $(SCALAR_OBJECTS) GIT-LDFLAGS $(GITLIBS)
2656+
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
2657+
$(filter %.o,$^) $(LIBS)
2658+
2659+
bin-wrappers/scalar: contrib/scalar/Makefile
2660+
$(QUIET_SUBDIR0)contrib/scalar $(QUIET_SUBDIR1) ../../bin-wrappers/scalar
2661+
26472662
git-gvfs-helper$X: gvfs-helper.o http.o GIT-LDFLAGS $(GITLIBS)
26482663
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
26492664
$(CURL_LIBCURL) $(EXPAT_LIBEXPAT) $(LIBS)
@@ -2667,14 +2682,23 @@ Documentation/GIT-EXCLUDED-PROGRAMS: FORCE
26672682
.PHONY: doc man man-perl html info pdf
26682683
doc: man-perl
26692684
$(MAKE) -C Documentation all
2685+
ifneq (,$(INCLUDE_SCALAR))
2686+
$(QUIET_SUBDIR0)contrib/scalar $(QUIET_SUBDIR1) scalar.html scalar.1
2687+
endif
26702688

26712689
man: man-perl
26722690
$(MAKE) -C Documentation man
2691+
ifneq (,$(INCLUDE_SCALAR))
2692+
$(QUIET_SUBDIR0)contrib/scalar $(QUIET_SUBDIR1) scalar.1
2693+
endif
26732694

26742695
man-perl: perl/build/man/man3/Git.3pm
26752696

26762697
html:
26772698
$(MAKE) -C Documentation html
2699+
ifneq (,$(INCLUDE_SCALAR))
2700+
$(QUIET_SUBDIR0)contrib/scalar $(QUIET_SUBDIR1) scalar.html
2701+
endif
26782702

26792703
info:
26802704
$(MAKE) -C Documentation info
@@ -2922,6 +2946,10 @@ endif
29222946

29232947
test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
29242948

2949+
ifneq (,$(INCLUDE_SCALAR))
2950+
test_bindir_programs += bin-wrappers/scalar
2951+
endif
2952+
29252953
all:: $(TEST_PROGRAMS) $(test_bindir_programs)
29262954

29272955
bin-wrappers/%: wrap-for-bin.sh
@@ -2942,6 +2970,9 @@ export TEST_NO_MALLOC_CHECK
29422970

29432971
test: all
29442972
$(MAKE) -C t/ all
2973+
ifneq (,$(INCLUDE_SCALAR))
2974+
$(MAKE) -C contrib/scalar/t
2975+
endif
29452976

29462977
perf: all
29472978
$(MAKE) -C t/perf/ all
@@ -3067,6 +3098,9 @@ install: all
30673098
$(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
30683099
$(INSTALL) -m 644 $(SCRIPT_LIB) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
30693100
$(INSTALL) $(install_bindir_programs) '$(DESTDIR_SQ)$(bindir_SQ)'
3101+
ifneq (,$(INCLUDE_SCALAR))
3102+
$(INSTALL) contrib/scalar/scalar$X '$(DESTDIR_SQ)$(bindir_SQ)'
3103+
endif
30703104
ifdef MSVC
30713105
# We DO NOT install the individual foo.o.pdb files because they
30723106
# have already been rolled up into the exe's pdb file.
@@ -3160,6 +3194,10 @@ install-doc: install-man-perl
31603194

31613195
install-man: install-man-perl
31623196
$(MAKE) -C Documentation install-man
3197+
ifneq (,$(INCLUDE_SCALAR))
3198+
$(MAKE) -C contrib/scalar scalar.1
3199+
$(INSTALL) contrib/scalar/scalar.1 '$(DESTDIR_SQ)$(mandir_SQ)/man1'
3200+
endif
31633201

31643202
install-man-perl: man-perl
31653203
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(mandir_SQ)/man3'
@@ -3168,6 +3206,10 @@ install-man-perl: man-perl
31683206

31693207
install-html:
31703208
$(MAKE) -C Documentation install-html
3209+
ifneq (,$(INCLUDE_SCALAR))
3210+
$(MAKE) -C contrib/scalar scalar.html
3211+
$(INSTALL) contrib/scalar/scalar.html '$(DESTDIR_SQ)$(htmldir)'
3212+
endif
31713213

31723214
install-info:
31733215
$(MAKE) -C Documentation install-info
@@ -3305,6 +3347,9 @@ endif
33053347
ifndef NO_TCLTK
33063348
$(MAKE) -C gitk-git clean
33073349
$(MAKE) -C git-gui clean
3350+
endif
3351+
ifneq (,$(INCLUDE_SCALAR))
3352+
$(MAKE) -C contrib/scalar clean
33083353
endif
33093354
$(RM) GIT-VERSION-FILE GIT-CFLAGS GIT-LDFLAGS GIT-BUILD-OPTIONS
33103355
$(RM) GIT-USER-AGENT GIT-PREFIX

builtin/gc.c

Lines changed: 70 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1619,18 +1619,40 @@ static int launchctl_remove_plists(const char *cmd)
16191619
launchctl_remove_plist(SCHEDULE_WEEKLY, cmd);
16201620
}
16211621

1622+
static int launchctl_list_contains_plist(const char *name, const char *cmd)
1623+
{
1624+
int result;
1625+
struct child_process child = CHILD_PROCESS_INIT;
1626+
char *uid = launchctl_get_uid();
1627+
1628+
strvec_split(&child.args, cmd);
1629+
strvec_pushl(&child.args, "list", name, NULL);
1630+
1631+
child.no_stderr = 1;
1632+
child.no_stdout = 1;
1633+
1634+
if (start_command(&child))
1635+
die(_("failed to start launchctl"));
1636+
1637+
result = finish_command(&child);
1638+
1639+
free(uid);
1640+
1641+
/* Returns failure if 'name' doesn't exist. */
1642+
return !result;
1643+
}
1644+
16221645
static int launchctl_schedule_plist(const char *exec_path, enum schedule_priority schedule, const char *cmd)
16231646
{
1624-
FILE *plist;
1625-
int i;
1647+
int i, fd;
16261648
const char *preamble, *repeat;
16271649
const char *frequency = get_frequency(schedule);
16281650
char *name = launchctl_service_name(frequency);
16291651
char *filename = launchctl_service_filename(name);
1630-
1631-
if (safe_create_leading_directories(filename))
1632-
die(_("failed to create directories for '%s'"), filename);
1633-
plist = xfopen(filename, "w");
1652+
struct lock_file lk = LOCK_INIT;
1653+
static unsigned long lock_file_timeout_ms = ULONG_MAX;
1654+
struct strbuf plist = STRBUF_INIT, plist2 = STRBUF_INIT;
1655+
struct stat st;
16341656

16351657
preamble = "<?xml version=\"1.0\"?>\n"
16361658
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
@@ -1649,7 +1671,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
16491671
"</array>\n"
16501672
"<key>StartCalendarInterval</key>\n"
16511673
"<array>\n";
1652-
fprintf(plist, preamble, name, exec_path, exec_path, frequency);
1674+
strbuf_addf(&plist, preamble, name, exec_path, exec_path, frequency);
16531675

16541676
switch (schedule) {
16551677
case SCHEDULE_HOURLY:
@@ -1658,7 +1680,7 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
16581680
"<key>Minute</key><integer>0</integer>\n"
16591681
"</dict>\n";
16601682
for (i = 1; i <= 23; i++)
1661-
fprintf(plist, repeat, i);
1683+
strbuf_addf(&plist, repeat, i);
16621684
break;
16631685

16641686
case SCHEDULE_DAILY:
@@ -1668,32 +1690,59 @@ static int launchctl_schedule_plist(const char *exec_path, enum schedule_priorit
16681690
"<key>Minute</key><integer>0</integer>\n"
16691691
"</dict>\n";
16701692
for (i = 1; i <= 6; i++)
1671-
fprintf(plist, repeat, i);
1693+
strbuf_addf(&plist, repeat, i);
16721694
break;
16731695

16741696
case SCHEDULE_WEEKLY:
1675-
fprintf(plist,
1676-
"<dict>\n"
1677-
"<key>Day</key><integer>0</integer>\n"
1678-
"<key>Hour</key><integer>0</integer>\n"
1679-
"<key>Minute</key><integer>0</integer>\n"
1680-
"</dict>\n");
1697+
strbuf_addstr(&plist,
1698+
"<dict>\n"
1699+
"<key>Day</key><integer>0</integer>\n"
1700+
"<key>Hour</key><integer>0</integer>\n"
1701+
"<key>Minute</key><integer>0</integer>\n"
1702+
"</dict>\n");
16811703
break;
16821704

16831705
default:
16841706
/* unreachable */
16851707
break;
16861708
}
1687-
fprintf(plist, "</array>\n</dict>\n</plist>\n");
1688-
fclose(plist);
1709+
strbuf_addstr(&plist, "</array>\n</dict>\n</plist>\n");
1710+
1711+
if (safe_create_leading_directories(filename))
1712+
die(_("failed to create directories for '%s'"), filename);
1713+
1714+
if ((long)lock_file_timeout_ms < 0 &&
1715+
git_config_get_ulong("gc.launchctlplistlocktimeoutms",
1716+
&lock_file_timeout_ms))
1717+
lock_file_timeout_ms = 150;
1718+
1719+
fd = hold_lock_file_for_update_timeout(&lk, filename, LOCK_DIE_ON_ERROR,
1720+
lock_file_timeout_ms);
16891721

1690-
/* bootout might fail if not already running, so ignore */
1691-
launchctl_boot_plist(0, filename, cmd);
1692-
if (launchctl_boot_plist(1, filename, cmd))
1693-
die(_("failed to bootstrap service %s"), filename);
1722+
/*
1723+
* Does this file already exist? With the intended contents? Is it
1724+
* registered already? Then it does not need to be re-registered.
1725+
*/
1726+
if (!stat(filename, &st) && st.st_size == plist.len &&
1727+
strbuf_read_file(&plist2, filename, plist.len) == plist.len &&
1728+
!strbuf_cmp(&plist, &plist2) &&
1729+
launchctl_list_contains_plist(name, cmd))
1730+
rollback_lock_file(&lk);
1731+
else {
1732+
if (write_in_full(fd, plist.buf, plist.len) < 0 ||
1733+
commit_lock_file(&lk))
1734+
die_errno(_("could not write '%s'"), filename);
1735+
1736+
/* bootout might fail if not already running, so ignore */
1737+
launchctl_boot_plist(0, filename, cmd);
1738+
if (launchctl_boot_plist(1, filename, cmd))
1739+
die(_("failed to bootstrap service %s"), filename);
1740+
}
16941741

16951742
free(filename);
16961743
free(name);
1744+
strbuf_release(&plist);
1745+
strbuf_release(&plist2);
16971746
return 0;
16981747
}
16991748

builtin/help.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,8 @@ static const char *cmd_to_page(const char *git_cmd)
395395
return git_cmd;
396396
else if (is_git_command(git_cmd))
397397
return xstrfmt("git-%s", git_cmd);
398+
else if (!strcmp("scalar", git_cmd))
399+
return xstrdup(git_cmd);
398400
else
399401
return xstrfmt("git%s", git_cmd);
400402
}

ci/run-test-slice.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,9 @@ make --quiet -C t T="$(cd t &&
1717
# Run the git subtree tests only if main tests succeeded
1818
test 0 != "$1" || make -C contrib/subtree test
1919

20+
if test 0 = "$1" && test -n "$INCLUDE_SCALAR"
21+
then
22+
make -C contrib/scalar/t
23+
fi
24+
2025
check_unignored_build_artifacts

config.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2999,6 +2999,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
29992999
const char *value_pattern,
30003000
unsigned flags)
30013001
{
3002+
static unsigned long timeout_ms = ULONG_MAX;
30023003
int fd = -1, in_fd = -1;
30033004
int ret;
30043005
struct lock_file lock = LOCK_INIT;
@@ -3019,11 +3020,16 @@ int git_config_set_multivar_in_file_gently(const char *config_filename,
30193020
if (!config_filename)
30203021
config_filename = filename_buf = git_pathdup("config");
30213022

3023+
if ((long)timeout_ms < 0 &&
3024+
git_config_get_ulong("core.configWriteLockTimeoutMS", &timeout_ms))
3025+
timeout_ms = 0;
3026+
30223027
/*
30233028
* The lock serves a purpose in addition to locking: the new
30243029
* contents of .git/config will be written into it.
30253030
*/
3026-
fd = hold_lock_file_for_update(&lock, config_filename, 0);
3031+
fd = hold_lock_file_for_update_timeout(&lock, config_filename, 0,
3032+
timeout_ms);
30273033
if (fd < 0) {
30283034
error_errno(_("could not lock config file %s"), config_filename);
30293035
ret = CONFIG_NO_LOCK;

contrib/buildsystems/CMakeLists.txt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,13 @@ if(CURL_FOUND)
751751
target_link_libraries(git-gvfs-helper http_obj common-main ${CURL_LIBRARIES} )
752752
endif()
753753

754+
if(DEFINED ENV{INCLUDE_SCALAR} AND NOT ENV{INCLUDE_SCALAR} STREQUAL "")
755+
add_executable(scalar ${CMAKE_SOURCE_DIR}/contrib/scalar/scalar.c ${CMAKE_SOURCE_DIR}/contrib/scalar/json-parser.c)
756+
target_link_libraries(scalar common-main)
757+
set_target_properties(scalar PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/contrib/scalar)
758+
set_target_properties(scalar PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/contrib/scalar)
759+
endif()
760+
754761
parse_makefile_for_executables(git_builtin_extra "BUILT_INS")
755762

756763
option(SKIP_DASHED_BUILT_INS "Skip hardlinking the dashed versions of the built-ins")
@@ -969,7 +976,6 @@ if(CURL_FOUND)
969976
endif()
970977
endif()
971978

972-
973979
foreach(script ${wrapper_scripts})
974980
file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME)
975981
string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
@@ -989,6 +995,13 @@ string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
989995
string(REPLACE "@@PROG@@" "git-cvsserver" content "${content}")
990996
file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/git-cvsserver ${content})
991997

998+
if(DEFINED ENV{INCLUDE_SCALAR} AND NOT ENV{INCLUDE_SCALAR} STREQUAL "")
999+
file(STRINGS ${CMAKE_SOURCE_DIR}/wrap-for-bin.sh content NEWLINE_CONSUME)
1000+
string(REPLACE "@@BUILD_DIR@@" "${CMAKE_BINARY_DIR}" content "${content}")
1001+
string(REPLACE "@@PROG@@" "contrib/scalar/scalar${EXE_EXTENSION}" content "${content}")
1002+
file(WRITE ${CMAKE_BINARY_DIR}/bin-wrappers/scalar ${content})
1003+
endif()
1004+
9921005
#options for configuring test options
9931006
option(PERL_TESTS "Perform tests that use perl" ON)
9941007
option(PYTHON_TESTS "Perform tests that use python" ON)

contrib/scalar/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/*.xml
2+
/*.1
3+
/*.html
4+
/*.exe
5+
/scalar

0 commit comments

Comments
 (0)