commit - d2ad595c2cf140e23c761ef62916dbc49b40f66b
commit + f7b97ccb29b3e414e360ff635f9bc114f8db7c2f
blob - 8438cb9700eb8696249c22aec54bfa6249f98bc5
blob + d17ff2d8455425992dbcd98fe8e0d53acfd2c208
--- include/got_error.h
+++ include/got_error.h
#define GOT_ERR_OK 0
#define GOT_ERR_ERRNO 1
#define GOT_ERR_NOT_GIT_REPO 2
-/* 3 is currently unused */
+#define GOT_ERR_BAD_FILETYPE 3
#define GOT_ERR_BAD_PATH 4
#define GOT_ERR_NOT_REF 5
#define GOT_ERR_IO 6
{ GOT_ERR_OK, "no error occured?!?" },
{ GOT_ERR_ERRNO, "see errno" },
{ GOT_ERR_NOT_GIT_REPO, "no git repository found" },
- { 3, "unused error code" },
+ { GOT_ERR_BAD_FILETYPE, "bad file type" },
{ GOT_ERR_BAD_PATH, "bad path" },
{ GOT_ERR_NOT_REF, "no such reference found" },
{ GOT_ERR_IO, "input/output error" },
blob - b9728b4ffb0613650c0438ce082ae6194bd635cc
blob + de279d7ac5f87f20be6173c3f7932fb898e2254d
--- lib/object_create.c
+++ lib/object_create.c
}
static const struct got_error *
-mode2str(char *buf, size_t len, mode_t mode)
+te_mode2str(char *buf, size_t len, mode_t te_mode)
{
int ret;
+ mode_t mode;
+
+ /*
+ * Some Git implementations are picky about modes seen in tree entries.
+ * For best compatibility we normalize the file/directory mode here.
+ * Note that we do not support committing symlinks or submodules.
+ */
+ if (S_ISREG(te_mode))
+ mode = GOT_DEFAULT_FILE_MODE;
+ else if (S_ISDIR(te_mode))
+ mode = GOT_DEFAULT_DIR_MODE;
+ else
+ return got_error(GOT_ERR_BAD_FILETYPE);
+ if (te_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
+ mode |= S_IXUSR | S_IXGRP | S_IXOTH;
+
ret = snprintf(buf, len, "%o ", mode);
if (ret == -1 || ret >= len)
return got_error(GOT_ERR_NO_SPACE);
for (i = 0; i < nentries; i++) {
te = sorted_entries[i];
- err = mode2str(modebuf, sizeof(modebuf), te->mode);
+ err = te_mode2str(modebuf, sizeof(modebuf), te->mode);
if (err)
goto done;
len += strlen(modebuf) + strlen(te->name) + 1 +
for (i = 0; i < nentries; i++) {
te = sorted_entries[i];
- err = mode2str(modebuf, sizeof(modebuf), te->mode);
+ err = te_mode2str(modebuf, sizeof(modebuf), te->mode);
if (err)
goto done;
len = strlen(modebuf);
blob - 270ee1fe177e6657aa51f55d0f13dae24a800402
blob + 0c80d8ca1cb82c44fdb5ac37032d91b93b191c92
--- regress/cmdline/commit.sh
+++ regress/cmdline/commit.sh
echo 'm alpha' > $testroot/stdout.expected
(cd $testroot/wt && got status > $testroot/stdout)
+
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ fi
+ test_done "$testroot" "$ret"
+}
+
+function commit_check_mode {
+ local mode="$1"
+ local expected_mode="$2"
+
+ chmod 644 $testroot/wt/alpha
+ echo a >> $testroot/wt/alpha
+ chmod $mode $testroot/wt/alpha
+
+ (cd $testroot/wt && got commit -mm > $testroot/stdout)
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ echo "got commit failed unexpectedly"
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ local commit_id=`git_show_head $testroot/repo`
+ echo 'M alpha' > $testroot/stdout.expected
+ echo "Created commit $commit_id" >> $testroot/stdout.expected
+ cmp -s $testroot/stdout.expected $testroot/stdout
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ diff -u $testroot/stdout.expected $testroot/stdout
+ test_done "$testroot" "$ret"
+ fi
+
+ local tree_id=$(got cat -r $testroot/repo $commit_id | \
+ grep ^tree | cut -d' ' -f2)
+ local alpha_id=$(got cat -r $testroot/repo $tree_id | \
+ grep 'alpha$' | cut -d' ' -f1)
+ echo "$alpha_id $expected_mode alpha" > $testroot/stdout.expected
+ got cat -r $testroot/repo $tree_id | grep 'alpha$' > $testroot/stdout
cmp -s $testroot/stdout.expected $testroot/stdout
ret="$?"
if [ "$ret" != "0" ]; then
diff -u $testroot/stdout.expected $testroot/stdout
fi
+ return $ret
+}
+
+function test_commit_normalizes_filemodes {
+ local testroot=`test_init commit_normalizes_filemodes`
+
+ got checkout $testroot/repo $testroot/wt > /dev/null
+ ret="$?"
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+
+ modes="600 400 460 640 440 660 444 666"
+ for m in $modes; do
+ commit_check_mode "$m" "0100644"
+ if [ "$ret" != "0" ]; then
+ break
+ fi
+ done
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
+ modes="700 500 570 750 550 770 555 777"
+ for m in $modes; do
+ commit_check_mode "$m" "0100755"
+ if [ "$ret" != "0" ]; then
+ break
+ fi
+ done
+ if [ "$ret" != "0" ]; then
+ test_done "$testroot" "$ret"
+ return 1
+ fi
test_done "$testroot" "$ret"
}
run_test test_commit_tree_entry_sorting
run_test test_commit_gitconfig_author
run_test test_commit_xbit_change
+run_test test_commit_normalizes_filemodes