mirror of
https://github.com/git/git.git
synced 2026-04-02 04:50:12 +02:00
Revert accidentally merged commits
This reverts the following commits:abd1fa1test-suite: Log everything to a file in non-verbose mode50f37d1Implement test-stat the prints the modification time.fc7fe85gitk: Swap positions of 'next' and 'prev' buttons in the 'Find' section.f80f1dbNeed diff -u -b in t7401 because some lines end in CRLF.85763c8Implement thread-specific die() routines; use one in start_async().4eb0463Make report() from usage.c public as vreport().ddce705Skip tests that fail due to incomplete implementations, missing tools...a094080Do not issue the warning about the fallback of the PREFIX. These were brought in by the merge commitdc8b641that merged my private work-in-progress branch. Only these two commits remain:1e52e22Windows: Work around intermittent failures in mingw_renameccd3859Windows: Better support PAGER settings with spaces in the path Signed-off-by: Johannes Sixt <j6t@kdbg.org>
This commit is contained in:
@@ -28,10 +28,9 @@ const char *system_path(const char *path)
|
||||
!(prefix = strip_path_suffix(argv0_path, BINDIR)) &&
|
||||
!(prefix = strip_path_suffix(argv0_path, "git"))) {
|
||||
prefix = PREFIX;
|
||||
/*
|
||||
* RUNTIME_PREFIX requested, but prefix computation failed.
|
||||
* Using static fallback.
|
||||
*/
|
||||
fprintf(stderr, "RUNTIME_PREFIX requested, "
|
||||
"but prefix computation failed. "
|
||||
"Using static fallback '%s'.\n", prefix);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -150,7 +150,6 @@
|
||||
#endif
|
||||
|
||||
/* General helper functions */
|
||||
extern void vreport(const char *prefix, const char *err, va_list params);
|
||||
extern void usage(const char *err) NORETURN;
|
||||
extern void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
|
||||
extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
|
||||
|
||||
@@ -2057,7 +2057,7 @@ proc makewindow {} {
|
||||
button .tf.lbar.fnext -text [mc "next"] -command {dofind 1 1}
|
||||
button .tf.lbar.fprev -text [mc "prev"] -command {dofind -1 1}
|
||||
label .tf.lbar.flab2 -text " [mc "commit"] "
|
||||
pack .tf.lbar.flabel .tf.lbar.fprev .tf.lbar.fnext .tf.lbar.flab2 \
|
||||
pack .tf.lbar.flabel .tf.lbar.fnext .tf.lbar.fprev .tf.lbar.flab2 \
|
||||
-side left -fill y
|
||||
set gdttype [mc "containing:"]
|
||||
set gm [tk_optionMenu .tf.lbar.gdttype gdttype \
|
||||
|
||||
@@ -293,22 +293,9 @@ int run_command_v_opt_cd_env(const char **argv, int opt, const char *dir, const
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
static int close_fd = -1;
|
||||
NORETURN void die_from_thread(const char *err, va_list params)
|
||||
{
|
||||
vreport("fatal: ", err, params);
|
||||
if (close_fd >= 0)
|
||||
close(close_fd);
|
||||
_endthreadex(128);
|
||||
exit(128); /* silence compiler */
|
||||
}
|
||||
|
||||
static __stdcall unsigned run_thread(void *data)
|
||||
{
|
||||
struct async *async = data;
|
||||
close_fd = async->fd_for_proc;
|
||||
extern NORETURN void die_from_thread(const char *err, va_list params);
|
||||
set_die_routine(die_from_thread);
|
||||
return async->proc(async->fd_for_proc, async->data);
|
||||
}
|
||||
#endif
|
||||
@@ -362,9 +349,6 @@ int finish_async(struct async *async)
|
||||
else if (!GetExitCodeThread(async->tid, &ret))
|
||||
ret = error("cannot get thread exit code: %lu", GetLastError());
|
||||
CloseHandle(async->tid);
|
||||
if (ret)
|
||||
/* test suite tests for this string */
|
||||
error("waitpid (async) failed");
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
1
t/.gitignore
vendored
1
t/.gitignore
vendored
@@ -1,3 +1,2 @@
|
||||
/trash directory*
|
||||
/test-results
|
||||
/test-log
|
||||
|
||||
23
t/Makefile
23
t/Makefile
@@ -21,7 +21,7 @@ $(T):
|
||||
@echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
|
||||
|
||||
pre-clean:
|
||||
$(RM) -r test-results test-log
|
||||
$(RM) -r test-results
|
||||
|
||||
clean:
|
||||
$(RM) -r 'trash directory'.* test-results
|
||||
@@ -42,24 +42,3 @@ valgrind:
|
||||
GIT_TEST_OPTS=--valgrind $(MAKE)
|
||||
|
||||
.PHONY: pre-clean $(T) aggregate-results clean valgrind
|
||||
|
||||
-include Makefile.local
|
||||
|
||||
GIT_SKIP_TESTS := $(GIT_SKIP_TESTS_LOCAL)
|
||||
# git am does not treat absolute path to mbox file correctly
|
||||
GIT_SKIP_TESTS += t4150.18
|
||||
# output contains CRLF (I think)
|
||||
GIT_SKIP_TESTS += t7401.14
|
||||
# output contains CRLF (I think)
|
||||
GIT_SKIP_TESTS += t7508.1[68]
|
||||
# cannot run fake.sendmail for some reason
|
||||
GIT_SKIP_TESTS += t9001
|
||||
# there's a problem with GIT_DIR in test 12 (why only there?)
|
||||
# needs fixups with $PWD instead of $(pwd) - tries to run rsh c
|
||||
GIT_SKIP_TESTS += t9200
|
||||
# CGI.pm not found
|
||||
GIT_SKIP_TESTS += t9500
|
||||
export GIT_SKIP_TESTS
|
||||
|
||||
NO_SVN_TESTS=SkipThem
|
||||
export NO_SVN_TESTS
|
||||
|
||||
@@ -39,7 +39,6 @@ Standard options
|
||||
EOF
|
||||
|
||||
test_expect_success 'test help' '
|
||||
set +x &&
|
||||
test_must_fail test-parse-options -h > output 2> output.err &&
|
||||
test ! -s output &&
|
||||
test_cmp expect.err output.err
|
||||
@@ -159,7 +158,6 @@ error: did you mean \`--boolean\` (with two dashes ?)
|
||||
EOF
|
||||
|
||||
test_expect_success 'detect possible typos' '
|
||||
set +x &&
|
||||
test_must_fail test-parse-options -boolean > output 2> output.err &&
|
||||
test ! -s output &&
|
||||
test_cmp typo.err output.err
|
||||
@@ -225,7 +223,6 @@ Callback: "not set", 1
|
||||
EOF
|
||||
|
||||
test_expect_success 'OPT_CALLBACK() and callback errors work' '
|
||||
set +x &&
|
||||
test_must_fail test-parse-options --no-length > output 2> output.err &&
|
||||
test_cmp expect output &&
|
||||
test_cmp expect.err output.err
|
||||
|
||||
@@ -71,7 +71,6 @@ test_expect_success 'fails with any bad rev or many good revs' '
|
||||
'
|
||||
|
||||
test_expect_success 'fails silently when using -q' '
|
||||
set +x &&
|
||||
test_must_fail git rev-parse --verify --quiet 2>error &&
|
||||
test -z "$(cat error)" &&
|
||||
test_must_fail git rev-parse -q --verify foo 2>error &&
|
||||
|
||||
@@ -245,7 +245,11 @@ test_expect_success 'am works from file (relative path given) in subdirectory' '
|
||||
test -z "$(git diff second)"
|
||||
'
|
||||
|
||||
test_expect_success 'am works from file (absolute path given) in subdirectory' '
|
||||
case $(uname -s) in
|
||||
*MINGW*) test_expect=test_expect_failure;;
|
||||
*) test_expect=test_expect_success;;
|
||||
esac
|
||||
$test_expect 'am works from file (absolute path given) in subdirectory' '
|
||||
rm -fr subdir &&
|
||||
git checkout first &&
|
||||
P=$(pwd) &&
|
||||
|
||||
@@ -247,7 +247,6 @@ EOF
|
||||
|
||||
test_expect_success 'set-head --auto fails w/multiple HEADs' '
|
||||
(cd test &&
|
||||
set +x &&
|
||||
test_must_fail git remote set-head --auto two >output 2>&1 &&
|
||||
test_cmp expect output)
|
||||
'
|
||||
|
||||
@@ -95,15 +95,30 @@ git checkout master'
|
||||
test_expect_success 'pull renaming branch into unrenaming one' \
|
||||
'
|
||||
git show-branch
|
||||
test_must_fail git pull . white &&
|
||||
git ls-files -s &&
|
||||
test "$(git ls-files -u B | wc -l)" -eq 3 &&
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 &&
|
||||
git pull . white && {
|
||||
echo "BAD: should have conflicted"
|
||||
return 1
|
||||
}
|
||||
git ls-files -s
|
||||
test "$(git ls-files -u B | wc -l)" -eq 3 || {
|
||||
echo "BAD: should have left stages for B"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 || {
|
||||
echo "BAD: should have merged N"
|
||||
return 1
|
||||
}
|
||||
sed -ne "/^g/{
|
||||
p
|
||||
q
|
||||
}" B | grep master &&
|
||||
test "$(git diff white N | wc -l)" -eq 0
|
||||
}" B | grep master || {
|
||||
echo "BAD: should have listed our change first"
|
||||
return 1
|
||||
}
|
||||
test "$(git diff white N | wc -l)" -eq 0 || {
|
||||
echo "BAD: should have taken colored branch"
|
||||
return 1
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'pull renaming branch into another renaming one' \
|
||||
@@ -111,44 +126,95 @@ test_expect_success 'pull renaming branch into another renaming one' \
|
||||
rm -f B
|
||||
git reset --hard
|
||||
git checkout red
|
||||
test_must_fail git pull . white &&
|
||||
test "$(git ls-files -u B | wc -l)" -eq 3 &&
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 &&
|
||||
git pull . white && {
|
||||
echo "BAD: should have conflicted"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -u B | wc -l)" -eq 3 || {
|
||||
echo "BAD: should have left stages"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 || {
|
||||
echo "BAD: should have merged N"
|
||||
return 1
|
||||
}
|
||||
sed -ne "/^g/{
|
||||
p
|
||||
q
|
||||
}" B | grep red &&
|
||||
test "$(git diff white N | wc -l)" -eq 0
|
||||
}" B | grep red || {
|
||||
echo "BAD: should have listed our change first"
|
||||
return 1
|
||||
}
|
||||
test "$(git diff white N | wc -l)" -eq 0 || {
|
||||
echo "BAD: should have taken colored branch"
|
||||
return 1
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'pull unrenaming branch into renaming one' \
|
||||
'
|
||||
git reset --hard
|
||||
git show-branch
|
||||
test_must_fail git pull . master &&
|
||||
test "$(git ls-files -u B | wc -l)" -eq 3 &&
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 &&
|
||||
git pull . master && {
|
||||
echo "BAD: should have conflicted"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -u B | wc -l)" -eq 3 || {
|
||||
echo "BAD: should have left stages"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 || {
|
||||
echo "BAD: should have merged N"
|
||||
return 1
|
||||
}
|
||||
sed -ne "/^g/{
|
||||
p
|
||||
q
|
||||
}" B | grep red &&
|
||||
test "$(git diff white N | wc -l)" -eq 0
|
||||
}" B | grep red || {
|
||||
echo "BAD: should have listed our change first"
|
||||
return 1
|
||||
}
|
||||
test "$(git diff white N | wc -l)" -eq 0 || {
|
||||
echo "BAD: should have taken colored branch"
|
||||
return 1
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'pull conflicting renames' \
|
||||
'
|
||||
git reset --hard
|
||||
git show-branch
|
||||
test_must_fail git pull . blue &&
|
||||
test "$(git ls-files -u A | wc -l)" -eq 1 &&
|
||||
test "$(git ls-files -u B | wc -l)" -eq 1 &&
|
||||
test "$(git ls-files -u C | wc -l)" -eq 1 &&
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 &&
|
||||
git pull . blue && {
|
||||
echo "BAD: should have conflicted"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -u A | wc -l)" -eq 1 || {
|
||||
echo "BAD: should have left a stage"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -u B | wc -l)" -eq 1 || {
|
||||
echo "BAD: should have left a stage"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -u C | wc -l)" -eq 1 || {
|
||||
echo "BAD: should have left a stage"
|
||||
return 1
|
||||
}
|
||||
test "$(git ls-files -s N | wc -l)" -eq 1 || {
|
||||
echo "BAD: should have merged N"
|
||||
return 1
|
||||
}
|
||||
sed -ne "/^g/{
|
||||
p
|
||||
q
|
||||
}" B | grep red &&
|
||||
test "$(git diff white N | wc -l)" -eq 0
|
||||
}" B | grep red || {
|
||||
echo "BAD: should have listed our change first"
|
||||
return 1
|
||||
}
|
||||
test "$(git diff white N | wc -l)" -eq 0 || {
|
||||
echo "BAD: should have taken colored branch"
|
||||
return 1
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'interference with untracked working tree file' '
|
||||
@@ -156,8 +222,14 @@ test_expect_success 'interference with untracked working tree file' '
|
||||
git reset --hard
|
||||
git show-branch
|
||||
echo >A this file should not matter
|
||||
test_must_fail git pull . white &&
|
||||
test -f A
|
||||
git pull . white && {
|
||||
echo "BAD: should have conflicted"
|
||||
return 1
|
||||
}
|
||||
test -f A || {
|
||||
echo "BAD: should have left A intact"
|
||||
return 1
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'interference with untracked working tree file' '
|
||||
@@ -167,8 +239,14 @@ test_expect_success 'interference with untracked working tree file' '
|
||||
git show-branch
|
||||
rm -f A
|
||||
echo >A this file should not matter
|
||||
test_must_fail git pull . red &&
|
||||
test -f A
|
||||
git pull . red && {
|
||||
echo "BAD: should have conflicted"
|
||||
return 1
|
||||
}
|
||||
test -f A || {
|
||||
echo "BAD: should have left A intact"
|
||||
return 1
|
||||
}
|
||||
'
|
||||
|
||||
test_expect_success 'interference with untracked working tree file' '
|
||||
@@ -178,8 +256,14 @@ test_expect_success 'interference with untracked working tree file' '
|
||||
git checkout -f master
|
||||
git tag -f anchor
|
||||
git show-branch
|
||||
git pull . yellow
|
||||
test ! -f M &&
|
||||
git pull . yellow || {
|
||||
echo "BAD: should have cleanly merged"
|
||||
return 1
|
||||
}
|
||||
test -f M && {
|
||||
echo "BAD: should have removed M"
|
||||
return 1
|
||||
}
|
||||
git reset --hard anchor
|
||||
'
|
||||
|
||||
@@ -192,8 +276,14 @@ test_expect_success 'updated working tree file should prevent the merge' '
|
||||
git show-branch
|
||||
echo >>M one line addition
|
||||
cat M >M.saved
|
||||
test_must_fail git pull . yellow &&
|
||||
diff M M.saved &&
|
||||
git pull . yellow && {
|
||||
echo "BAD: should have complained"
|
||||
return 1
|
||||
}
|
||||
diff M M.saved || {
|
||||
echo "BAD: should have left M intact"
|
||||
return 1
|
||||
}
|
||||
rm -f M.saved
|
||||
'
|
||||
|
||||
@@ -207,8 +297,14 @@ test_expect_success 'updated working tree file should prevent the merge' '
|
||||
echo >>M one line addition
|
||||
cat M >M.saved
|
||||
git update-index M
|
||||
test_must_fail git pull . yellow &&
|
||||
diff M M.saved &&
|
||||
git pull . yellow && {
|
||||
echo "BAD: should have complained"
|
||||
return 1
|
||||
}
|
||||
diff M M.saved || {
|
||||
echo "BAD: should have left M intact"
|
||||
return 1
|
||||
}
|
||||
rm -f M.saved
|
||||
'
|
||||
|
||||
@@ -220,9 +316,18 @@ test_expect_success 'interference with untracked working tree file' '
|
||||
git tag -f anchor
|
||||
git show-branch
|
||||
echo >M this file should not matter
|
||||
git pull . master &&
|
||||
test -f M &&
|
||||
! (git ls-files -s | grep M) &&
|
||||
git pull . master || {
|
||||
echo "BAD: should have cleanly merged"
|
||||
return 1
|
||||
}
|
||||
test -f M || {
|
||||
echo "BAD: should have left M intact"
|
||||
return 1
|
||||
}
|
||||
git ls-files -s | grep M && {
|
||||
echo "BAD: M must be untracked in the result"
|
||||
return 1
|
||||
}
|
||||
git reset --hard anchor
|
||||
'
|
||||
|
||||
|
||||
@@ -73,12 +73,33 @@ test_expect_success 'merge white into red (A->B,M->N)' \
|
||||
'
|
||||
git checkout -b red-white red &&
|
||||
git merge white &&
|
||||
git write-tree >/dev/null &&
|
||||
test -f B &&
|
||||
test -f N &&
|
||||
test -f R &&
|
||||
! test -f A &&
|
||||
! test -f M
|
||||
git write-tree >/dev/null || {
|
||||
echo "BAD: merge did not complete"
|
||||
return 1
|
||||
}
|
||||
|
||||
test -f B || {
|
||||
echo "BAD: B does not exist in working directory"
|
||||
return 1
|
||||
}
|
||||
test -f N || {
|
||||
echo "BAD: N does not exist in working directory"
|
||||
return 1
|
||||
}
|
||||
test -f R || {
|
||||
echo "BAD: R does not exist in working directory"
|
||||
return 1
|
||||
}
|
||||
|
||||
test -f A && {
|
||||
echo "BAD: A still exists in working directory"
|
||||
return 1
|
||||
}
|
||||
test -f M && {
|
||||
echo "BAD: M still exists in working directory"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
'
|
||||
|
||||
# This test broke in 8371234ecaaf6e14fe3f2082a855eff1bbd79ae9
|
||||
@@ -87,12 +108,32 @@ test_expect_success 'merge blue into white (A->B, mod A, A untracked)' \
|
||||
git checkout -b white-blue white &&
|
||||
echo dirty >A &&
|
||||
git merge blue &&
|
||||
git write-tree >/dev/null &&
|
||||
test -f A &&
|
||||
test `cat A` = dirty &&
|
||||
test -f B &&
|
||||
test -f N &&
|
||||
! test -f M
|
||||
git write-tree >/dev/null || {
|
||||
echo "BAD: merge did not complete"
|
||||
return 1
|
||||
}
|
||||
|
||||
test -f A || {
|
||||
echo "BAD: A does not exist in working directory"
|
||||
return 1
|
||||
}
|
||||
test `cat A` = dirty || {
|
||||
echo "BAD: A content is wrong"
|
||||
return 1
|
||||
}
|
||||
test -f B || {
|
||||
echo "BAD: B does not exist in working directory"
|
||||
return 1
|
||||
}
|
||||
test -f N || {
|
||||
echo "BAD: N does not exist in working directory"
|
||||
return 1
|
||||
}
|
||||
test -f M && {
|
||||
echo "BAD: M still exists in working directory"
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
'
|
||||
|
||||
test_done
|
||||
|
||||
@@ -14,8 +14,6 @@ esac
|
||||
|
||||
. ./test-lib.sh
|
||||
|
||||
export GIT_TEST_CMP='diff -u -b' # some lines end in CRLF
|
||||
|
||||
add_file () {
|
||||
sm=$1
|
||||
shift
|
||||
|
||||
@@ -399,8 +399,20 @@ from refs/heads/branch
|
||||
INPUT_END
|
||||
test_expect_success \
|
||||
'F: non-fast-forward update skips' \
|
||||
'test_must_fail git fast-import <input &&
|
||||
test $old_branch = `git rev-parse --verify branch^0`
|
||||
'if git fast-import <input
|
||||
then
|
||||
echo BAD gfi did not fail
|
||||
return 1
|
||||
else
|
||||
if test $old_branch = `git rev-parse --verify branch^0`
|
||||
then
|
||||
: branch unaffected and failure returned
|
||||
return 0
|
||||
else
|
||||
echo BAD gfi changed branch $old_branch
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
'
|
||||
test_expect_success \
|
||||
'F: verify pack' \
|
||||
|
||||
@@ -60,7 +60,6 @@ export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
|
||||
export GIT_COMMITTER_EMAIL GIT_COMMITTER_NAME
|
||||
export EDITOR VISUAL
|
||||
GIT_TEST_CMP=${GIT_TEST_CMP:-diff -u}
|
||||
TEST_DIRECTORY=$(pwd)
|
||||
|
||||
# Protect ourselves from common misconfiguration to export
|
||||
# CDPATH into the environment
|
||||
@@ -168,15 +167,9 @@ fi
|
||||
exec 5>&1
|
||||
if test "$verbose" = "t"
|
||||
then
|
||||
set_x= set_nox=
|
||||
exec 4>&2 3>&1
|
||||
else
|
||||
test_log_dir="$TEST_DIRECTORY/test-log"
|
||||
mkdir -p "$test_log_dir"
|
||||
test_log_path="$test_log_dir/${0%.sh}-$$"
|
||||
set_x='set -x;'
|
||||
set_nox='set +x'
|
||||
exec 3>"$test_log_path" 4>&3
|
||||
exec 4>/dev/null 3>/dev/null
|
||||
fi
|
||||
|
||||
test_failure=0
|
||||
@@ -310,9 +303,8 @@ test_debug () {
|
||||
}
|
||||
|
||||
test_run_ () {
|
||||
eval >&3 2>&4 $set_x "$1" '
|
||||
eval_ret=$?
|
||||
$set_nox'
|
||||
eval >&3 2>&4 "$1"
|
||||
eval_ret="$?"
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -548,6 +540,7 @@ test_done () {
|
||||
|
||||
# Test the binaries we have just built. The tests are kept in
|
||||
# t/ subdirectory and are run in 'trash directory' subdirectory.
|
||||
TEST_DIRECTORY=$(pwd)
|
||||
if test -z "$valgrind"
|
||||
then
|
||||
if test -z "$GIT_TEST_INSTALLED"
|
||||
|
||||
170
test-stat.c
170
test-stat.c
@@ -1,170 +0,0 @@
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef EMULATE
|
||||
#define HINT fprintf(stderr, "emulated stat\n")
|
||||
#include <errno.h>
|
||||
#include <windows.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Use mingw_lstat() instead of lstat()/stat() and
|
||||
* mingw_fstat() instead of fstat() on Windows.
|
||||
*/
|
||||
int mingw_lstat(const char *file_name, struct stat *buf);
|
||||
int mingw_fstat(int fd, struct stat *buf);
|
||||
#define fstat mingw_fstat
|
||||
#define lstat mingw_lstat
|
||||
#define stat(x,y) mingw_lstat(x,y)
|
||||
|
||||
#define PATH_MAX 260
|
||||
|
||||
static inline int file_attr_to_st_mode (DWORD attr)
|
||||
{
|
||||
int fMode = S_IREAD;
|
||||
if (attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
fMode |= S_IFDIR;
|
||||
else
|
||||
fMode |= S_IFREG;
|
||||
if (!(attr & FILE_ATTRIBUTE_READONLY))
|
||||
fMode |= S_IWRITE;
|
||||
return fMode;
|
||||
}
|
||||
|
||||
static inline int get_file_attr(const char *fname, WIN32_FILE_ATTRIBUTE_DATA *fdata)
|
||||
{
|
||||
if (GetFileAttributesExA(fname, GetFileExInfoStandard, fdata))
|
||||
return 0;
|
||||
|
||||
switch (GetLastError()) {
|
||||
case ERROR_ACCESS_DENIED:
|
||||
case ERROR_SHARING_VIOLATION:
|
||||
case ERROR_LOCK_VIOLATION:
|
||||
case ERROR_SHARING_BUFFER_EXCEEDED:
|
||||
return EACCES;
|
||||
case ERROR_BUFFER_OVERFLOW:
|
||||
return ENAMETOOLONG;
|
||||
case ERROR_NOT_ENOUGH_MEMORY:
|
||||
return ENOMEM;
|
||||
default:
|
||||
return ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
static inline time_t filetime_to_time_t(const FILETIME *ft)
|
||||
{
|
||||
long long winTime = ((long long)ft->dwHighDateTime << 32) + ft->dwLowDateTime;
|
||||
winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
|
||||
winTime /= 10000000; /* Nano to seconds resolution */
|
||||
return (time_t)winTime;
|
||||
}
|
||||
|
||||
/* We keep the do_lstat code in a separate function to avoid recursion.
|
||||
* When a path ends with a slash, the stat will fail with ENOENT. In
|
||||
* this case, we strip the trailing slashes and stat again.
|
||||
*/
|
||||
static int do_lstat(const char *file_name, struct stat *buf)
|
||||
{
|
||||
WIN32_FILE_ATTRIBUTE_DATA fdata;
|
||||
|
||||
if (!(errno = get_file_attr(file_name, &fdata))) {
|
||||
buf->st_ino = 0;
|
||||
buf->st_gid = 0;
|
||||
buf->st_uid = 0;
|
||||
buf->st_nlink = 1;
|
||||
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
|
||||
buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
|
||||
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
|
||||
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
|
||||
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
|
||||
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* We provide our own lstat/fstat functions, since the provided
|
||||
* lstat/fstat functions are so slow. These stat functions are
|
||||
* tailored for Git's usage (read: fast), and are not meant to be
|
||||
* complete. Note that Git stat()s are redirected to mingw_lstat()
|
||||
* too, since Windows doesn't really handle symlinks that well.
|
||||
*/
|
||||
int mingw_lstat(const char *file_name, struct stat *buf)
|
||||
{
|
||||
int namelen;
|
||||
static char alt_name[PATH_MAX];
|
||||
|
||||
if (!do_lstat(file_name, buf))
|
||||
return 0;
|
||||
|
||||
/* if file_name ended in a '/', Windows returned ENOENT;
|
||||
* try again without trailing slashes
|
||||
*/
|
||||
if (errno != ENOENT)
|
||||
return -1;
|
||||
|
||||
namelen = strlen(file_name);
|
||||
if (namelen && file_name[namelen-1] != '/')
|
||||
return -1;
|
||||
while (namelen && file_name[namelen-1] == '/')
|
||||
--namelen;
|
||||
if (!namelen || namelen >= PATH_MAX)
|
||||
return -1;
|
||||
|
||||
memcpy(alt_name, file_name, namelen);
|
||||
alt_name[namelen] = 0;
|
||||
return do_lstat(alt_name, buf);
|
||||
}
|
||||
|
||||
#undef fstat
|
||||
int mingw_fstat(int fd, struct stat *buf)
|
||||
{
|
||||
HANDLE fh = (HANDLE)_get_osfhandle(fd);
|
||||
BY_HANDLE_FILE_INFORMATION fdata;
|
||||
|
||||
if (fh == INVALID_HANDLE_VALUE) {
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
/* direct non-file handles to MS's fstat() */
|
||||
if (GetFileType(fh) != FILE_TYPE_DISK)
|
||||
return fstat(fd, buf);
|
||||
|
||||
if (GetFileInformationByHandle(fh, &fdata)) {
|
||||
buf->st_ino = 0;
|
||||
buf->st_gid = 0;
|
||||
buf->st_uid = 0;
|
||||
buf->st_nlink = 1;
|
||||
buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
|
||||
buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */
|
||||
buf->st_dev = buf->st_rdev = 0; /* not used by Git */
|
||||
buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime));
|
||||
buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime));
|
||||
buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime));
|
||||
return 0;
|
||||
}
|
||||
errno = EBADF;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#else
|
||||
#define HINT (void)0
|
||||
#endif
|
||||
|
||||
int main(int argc, char**argv)
|
||||
{
|
||||
int i;
|
||||
int err = 0;
|
||||
HINT;
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(argv[i], &st)) {
|
||||
perror(argv[i]);
|
||||
err = 1;
|
||||
continue;
|
||||
}
|
||||
printf("%s: %s\n", argv[i], ctime(&st.st_mtime));
|
||||
}
|
||||
return err;
|
||||
}
|
||||
40
usage.c
40
usage.c
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
#include "git-compat-util.h"
|
||||
|
||||
void vreport(const char *prefix, const char *err, va_list params)
|
||||
static void report(const char *prefix, const char *err, va_list params)
|
||||
{
|
||||
char msg[1024];
|
||||
vsnprintf(msg, sizeof(msg), err, params);
|
||||
@@ -20,52 +20,30 @@ static NORETURN void usage_builtin(const char *err)
|
||||
|
||||
static NORETURN void die_builtin(const char *err, va_list params)
|
||||
{
|
||||
vreport("fatal: ", err, params);
|
||||
report("fatal: ", err, params);
|
||||
exit(128);
|
||||
}
|
||||
|
||||
static void error_builtin(const char *err, va_list params)
|
||||
{
|
||||
vreport("error: ", err, params);
|
||||
report("error: ", err, params);
|
||||
}
|
||||
|
||||
static void warn_builtin(const char *warn, va_list params)
|
||||
{
|
||||
vreport("warning: ", warn, params);
|
||||
report("warning: ", warn, params);
|
||||
}
|
||||
|
||||
typedef void (*die_fn_t)(const char *err, va_list params) NORETURN;
|
||||
|
||||
static DWORD tls_index;
|
||||
|
||||
static void tls_init(void) __attribute__((constructor));
|
||||
static void tls_init(void)
|
||||
{
|
||||
tls_index = TlsAlloc();
|
||||
}
|
||||
|
||||
struct routines {
|
||||
die_fn_t die_routine;
|
||||
};
|
||||
/* If we are in a dlopen()ed .so write to a global variable would segfault
|
||||
* (ugh), so keep things static. */
|
||||
static void (*usage_routine)(const char *err) NORETURN = usage_builtin;
|
||||
static void (*die_routine)(const char *err, va_list params) NORETURN = die_builtin;
|
||||
static void (*error_routine)(const char *err, va_list params) = error_builtin;
|
||||
static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
|
||||
|
||||
void set_die_routine(void (*routine)(const char *err, va_list params) NORETURN)
|
||||
{
|
||||
struct routines *r = TlsGetValue(tls_index);
|
||||
if (r == NULL) {
|
||||
/* avoid die()! */
|
||||
r = calloc(sizeof(*r), 1);
|
||||
if (r == NULL) {
|
||||
fprintf(stderr, "cannot allocate thread-local storage");
|
||||
return;
|
||||
}
|
||||
TlsSetValue(tls_index, r);
|
||||
}
|
||||
r->die_routine = routine;
|
||||
die_routine = routine;
|
||||
}
|
||||
|
||||
void usage(const char *err)
|
||||
@@ -76,13 +54,9 @@ void usage(const char *err)
|
||||
void die(const char *err, ...)
|
||||
{
|
||||
va_list params;
|
||||
struct routines *r = TlsGetValue(tls_index);
|
||||
|
||||
va_start(params, err);
|
||||
if (r == NULL || r->die_routine == NULL)
|
||||
die_builtin(err, params);
|
||||
else
|
||||
r->die_routine(err, params);
|
||||
die_routine(err, params);
|
||||
va_end(params);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user