commit 63c5ca5de411be54e75480b0efec04014ffab46e from: Stefan Sperling date: Sat Aug 24 18:56:15 2019 UTC detect and ignore Git submodules commit - 2a06fe5f59f1b7b42f63bd9afe5187935c341321 commit + 63c5ca5de411be54e75480b0efec04014ffab46e blob - 45c8c5cc48c35aa3cd1e7e967be8cc112febeff7 blob + ffc4d0796f9263c15cc1a6ce02ca1ffbd707328f --- got/got.1 +++ got/got.1 @@ -405,6 +405,7 @@ annotations: .It @ Ta entry is a symbolic link .It / Ta entry is a directory .It * Ta entry is an executable file +.It $ Ta entry is a Git submodule .El .Pp If no blob - 34e071967697fcabd8e050f2be3856f67a3cacee blob + 77942a84ae2f6687f4c1b016ab97b7fcc7578feb --- got/got.c +++ got/got.c @@ -2511,7 +2511,9 @@ print_entry(struct got_tree_entry *te, const char *id, while (path[0] == '/') path++; - if (S_ISLNK(te->mode)) + if (got_object_tree_entry_is_submodule(te)) + modestr = "$"; + else if (S_ISLNK(te->mode)) modestr = "@"; else if (S_ISDIR(te->mode)) modestr = "/"; blob - 93db9af0036c3dc58da8d9f1c76664ddf7fde238 blob + 8063afe6c8c64dee5df429c78330e6af4c4deb3b --- include/got_object.h +++ include/got_object.h @@ -186,6 +186,9 @@ const struct got_tree_entries *got_object_tree_get_ent const struct got_tree_entry *got_object_tree_find_entry( struct got_tree_object *, const char *); +/* Return non-zero if the specified tree entry is a Git submodule. */ +int got_object_tree_entry_is_submodule(const struct got_tree_entry *); + /* * Compare two trees and indicate whether the entry at the specified path * differs between them. The path must not be the root path "/"; the function blob - 3c3c3397cc0c1896e190ac74c4ac314c5dc6e550 blob + e269983fad8691f00210e955a6383796011dcfc7 --- lib/diff.c +++ lib/diff.c @@ -497,6 +497,9 @@ diff_entry_old_new(const struct got_tree_entry *te1, { const struct got_error *err = NULL; int id_match; + + if (got_object_tree_entry_is_submodule(te1)) + return NULL; if (te2 == NULL) { if (S_ISDIR(te1->mode)) @@ -511,7 +514,8 @@ diff_entry_old_new(const struct got_tree_entry *te1, label1, NULL, repo); } return err; - } + } else if (got_object_tree_entry_is_submodule(te2)) + return NULL; id_match = (got_object_id_cmp(te1->id, te2->id) == 0); if (S_ISDIR(te1->mode) && S_ISDIR(te2->mode)) { @@ -543,6 +547,9 @@ diff_entry_new_old(const struct got_tree_entry *te2, int diff_content) { if (te1 != NULL) /* handled by diff_entry_old_new() */ + return NULL; + + if (got_object_tree_entry_is_submodule(te2)) return NULL; if (S_ISDIR(te2->mode)) blob - 1f0d5de40d9e53338b3595c9b4cbdf20e30ad8a5 blob + 696ab23bd6d6225884a016c70864988c476f669f --- lib/fileindex.c +++ lib/fileindex.c @@ -704,7 +704,7 @@ walk_tree(struct got_tree_entry **next, struct got_fil { const struct got_error *err = NULL; - if (S_ISDIR(te->mode)) { + if (!got_object_tree_entry_is_submodule(te) && S_ISDIR(te->mode)) { char *subpath; struct got_tree_object *subtree; @@ -756,7 +756,9 @@ diff_fileindex_tree(struct got_fileindex *fileindex, free(te_path); if (cmp == 0) { if (got_path_is_child((*ie)->path, path, - path_len) && (entry_name == NULL || + path_len) && + !got_object_tree_entry_is_submodule(te) && + (entry_name == NULL || strcmp(te->name, entry_name) == 0)) { err = cb->diff_old_new(cb_arg, *ie, te, path); @@ -799,8 +801,9 @@ diff_fileindex_tree(struct got_fileindex *fileindex, } *ie = next; } else if (te) { - if (entry_name == NULL || - strcmp(te->name, entry_name) == 0) { + if (!got_object_tree_entry_is_submodule(te) && + (entry_name == NULL || + strcmp(te->name, entry_name) == 0)) { err = cb->diff_new(cb_arg, te, path); if (err || entry_name) break; blob - 72be8b628623db608bfe5c38242bcd135e8425cd blob + e5c043ce567c8eb883622b2a78b71bb9ba64227d --- lib/object.c +++ lib/object.c @@ -1676,4 +1676,10 @@ done: *new_te = NULL; } return err; +} + +int +got_object_tree_entry_is_submodule(const struct got_tree_entry *te) +{ + return (te->mode & S_IFMT) == (S_IFDIR | S_IFLNK); } blob - 9a7c693b6fe913d70e282679c979cb7a7af850c3 blob + 8921d44e97b711564ee7ae00213598871b7242e3 --- lib/worktree.c +++ lib/worktree.c @@ -1426,6 +1426,9 @@ diff_new(void *arg, struct got_tree_entry *te, const c if (a->cancel_cb && a->cancel_cb(a->cancel_arg)) return got_error(GOT_ERR_CANCELLED); + if (got_object_tree_entry_is_submodule(te)) + return NULL; + if (asprintf(&path, "%s%s%s", parent_path, parent_path[0] ? "/" : "", te->name) == -1) @@ -3834,6 +3837,17 @@ write_tree(struct got_object_id **new_tree_id, base_entries = got_object_tree_get_entries(base_tree); SIMPLEQ_FOREACH(te, &base_entries->head, entry) { struct got_commitable *ct = NULL; + + if (got_object_tree_entry_is_submodule(te)) { + /* Entry is a submodule; just copy it. */ + err = got_object_tree_entry_dup(&new_te, te); + if (err) + goto done; + err = insert_tree_entry(new_te, &paths); + if (err) + goto done; + continue; + } if (S_ISDIR(te->mode)) { int modified; blob - b967040ffd7b21b1c0cda99ba37b84c58b0a8cb3 blob + 76ad000185ee0b02fa1a80d4ee24110a2fab7191 --- regress/cmdline/checkout.sh +++ regress/cmdline/checkout.sh @@ -251,10 +251,55 @@ function test_checkout_tag { fi test_done "$testroot" "$ret" } + +function test_checkout_ignores_submodules { + local testroot=`test_init checkout_ignores_submodules` + + (cd $testroot && git clone -q repo repo2 >/dev/null) + (cd $testroot/repo && git submodule -q add ../repo2) + (cd $testroot/repo && git commit -q -m 'adding submodule') + + echo "A $testroot/wt/.gitmodules" > $testroot/stdout.expected + echo "A $testroot/wt/alpha" >> $testroot/stdout.expected + echo "A $testroot/wt/beta" >> $testroot/stdout.expected + echo "A $testroot/wt/epsilon/zeta" >> $testroot/stdout.expected + echo "A $testroot/wt/gamma/delta" >> $testroot/stdout.expected + echo "Now shut up and hack" >> $testroot/stdout.expected + got checkout $testroot/repo $testroot/wt > $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + test_done "$testroot" "$ret" + return 1 + fi + + cmp -s $testroot/stdout.expected $testroot/stdout + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/stdout.expected $testroot/stdout + test_done "$testroot" "$ret" + return 1 + fi + + echo "alpha" > $testroot/content.expected + echo "beta" >> $testroot/content.expected + echo "zeta" >> $testroot/content.expected + echo "delta" >> $testroot/content.expected + cat $testroot/wt/alpha $testroot/wt/beta $testroot/wt/epsilon/zeta \ + $testroot/wt/gamma/delta > $testroot/content + + cmp -s $testroot/content.expected $testroot/content + ret="$?" + if [ "$ret" != "0" ]; then + diff -u $testroot/content.expected $testroot/content + fi + test_done "$testroot" "$ret" +} + run_test test_checkout_basic run_test test_checkout_dir_exists run_test test_checkout_dir_not_empty run_test test_checkout_sets_xbit run_test test_checkout_commit_from_wrong_branch run_test test_checkout_tag +run_test test_checkout_ignores_submodules blob - 46ebc3a92caf8f4523fa205630faacccc3fa263e blob + 4af5ca7c1f56bf6f604dc53635ac15ce4a13edb1 --- tog/tog.1 +++ tog/tog.1 @@ -247,6 +247,7 @@ Displayed tree entries may carry one of the following .It @ Ta entry is a symbolic link .It / Ta entry is a directory .It * Ta entry is an executable file +.It $ Ta entry is a Git submodule .El .Pp The key bindings for blob - d5a10ac995e03463cd40984b797f33f7f214f61d blob + fbc6df447875424b0d5974612adb03ccbb793fdf --- tog/tog.c +++ tog/tog.c @@ -3935,7 +3935,9 @@ draw_tree_entries(struct tog_view *view, return got_error_from_errno( "got_object_id_str"); } - if (S_ISLNK(te->mode)) + if (got_object_tree_entry_is_submodule(te)) + modestr = "$"; + else if (S_ISLNK(te->mode)) modestr = "@"; else if (S_ISDIR(te->mode)) modestr = "/";