From: James Cook Subject: got log -b path gets confused by merge commits To: gameoftrees@openbsd.org Date: Sun, 28 Jan 2024 18:34:17 +0000 I've managed to trigger the error got: //d/g: no such entry found in tree by running got log -b d/g or tog log -b d/g in a specially crafted repo. I have a script (at bottom) to reproduce and am happy to turn that into a patch for regress/cmdline. However, I have only partly understood the cause of the problem. Some notes below. Maybe someone more familiar with how advance_branch is supposed to work can see it more quickly. My commit graph looks like this (starting with the most recent commit): o create d/g | o merge (does not touch the directory d at all) / \ o o unrelated changes which leave the whole directory d unchanged \ / o initial commit, which includes directory d but without the file d/g I noticed that when detect_changed_path is called at commit_graph:508, and *commit_id is the merge commit, detect_changed_path sets changed to 0 and returns no error. (Line number 508 is from commit d4fbd6eb.) This is interesting because the path "d/g" is not present in that commit, and the if statement immediately following seems to be looking for that case (comparing err->code to GOT_ERR_NO_OBJ). The reason detect_changed_path doesn't return GOT_ERR_NO_OBJ is that the director d is not changed in the merge commit, so got_object_tree_path_changed stops walking the tree before it tries to look up d/g. I don't actually know if that's where the bug is because I don't know how it's all supposed to work. Interestingly, the bug doesn't appear without the -b option to {got,tog} log. FYI here is a backtrace from when got_error_path gets called (line numbers from commit d4fbd6eb): #0 got_error_path (path=0x0, code=31040) at /home/falsifian/co/got/got/../lib/error.c:437 #1 0x000006517031869b in got_object_tree_find_path (id=0x7940d1e13d60, mode=0x0, repo=0x6544d0b1450, tree=0x654541d49c0, path=0x654541fbea0 "/d/g") at /home/falsifian/co/got/got/../lib/object.c:591 #2 0x00000651703188e0 in got_object_id_by_path (id=0x7940d1e13d60, repo=0x6544d0b1450, commit=0x654541d8240, path=0x654541fbea0 "/d/g") at /home/falsifian/co/got/got/../lib/object.c:645 #3 0x000006517030985b in advance_branch (graph=0x654541eb440, commit_id=0x654541f60f0, commit=0x654541d8240, repo=0x6544d0b1450) at /home/falsifian/co/got/got/../lib/commit_graph.c:295 #4 0x0000065170308bf3 in fetch_commits_from_open_branches (graph=0x654541eb440, repo=0x6544d0b1450, cancel_cb=0x651702f77d0 , cancel_arg=0x0) at /home/falsifian/co/got/got/../lib/commit_graph.c:527 #5 0x0000065170308d53 in got_commit_graph_iter_next (id=0x7940d1e14010, graph=0x654541eb440, repo=0x6544d0b1450, cancel_cb=0x651702f77d0 , cancel_arg=0x0) at /home/falsifian/co/got/got/../lib/commit_graph.c:610 #6 0x00000651702f82dc in print_commits (root_id=0x654541d1d40, end_id=0x0, repo=0x6544d0b1450, path=0x6544d0cbd80 "/d/g", show_changed_paths=0, show_diffstat=0, show_patch=0, search_pattern=0x0, diff_context=3, limit=0, log_branches=1, reverse_display_order=0, refs_idmap=0x654541e90b0, one_line=0, tmpfile=0x0) at /home/falsifian/co/got/got/got.c:4492 #7 0x00000651702e4926 in cmd_log (argc=1, argv=0x7940d1e143a0) at /home/falsifian/co/got/got/got.c:4871 #8 0x00000651702decd7 in main (argc=5, argv=0x7940d1e14380) at /home/falsifian/co/got/got/got.c:262 -- James #!/bin/sh set -e mkdir bug; cd bug gotadmin init repo.git mkdir -p init/d echo content > init/d/f got import -r repo.git -m init init got co repo.git cd repo got br aux echo aux > aux got add aux got ci -m 'change on aux' got up -b main echo main > main got add main got ci -m 'change on main' got up got mg aux touch d/g got add d/g got ci -m 'create d/g' got log -b d/g