Fossil User Forum

fossil export: Non-existent SHA-1/SHA-3 in marks file error
Login

fossil export: Non-existent SHA-1/SHA-3 in marks file error

fossil export: Non-existent SHA-1/SHA-3 in marks file error

(1) By anonymous on 2023-07-22 11:35:31 [link] [source]

Howdy,

I've gotten this error when trying to incrementally update a git repo:

$ /usr/bin/fossil export --git --import-marks fossil-marks --export-marks fossil-marks repo.fossil
Non-existent SHA-1/SHA-3 in marks file: facec13bc95a8fb41aa1ef53a256ff373bd9a43f6e21623e0b5f0993bbf17dce
error importing marks from file: fossil-marks

I've done some digging and think that my problem is that repo.fossil is not the original fossil repo used to first export to the git repo. Its blob table has uuid's mapped to different rid values to that of the original fossil repo.

Examining the failing repo, working repo and marks file (with fossil sql command banner text removed):

$ fossil sql -R repo.fossil
sqlite> select rid from blob where uuid = 'facec13bc95a8fb41aa1ef53a256ff373bd9a43f6e21623e0b5f0993bbf17dce';
91

$ fossil sql -R original-working/repo.fossil 
sqlite> select rid from blob where uuid = 'facec13bc95a8fb41aa1ef53a256ff373bd9a43f6e21623e0b5f0993bbf17dce';
107

$ grep facec13bc95a8fb41aa1ef53a256ff373bd9a43f6e21623e0b5f0993bbf17dce fossil-marks 
b107 :155 facec13bc95a8fb41aa1ef53a256ff373bd9a43f6e21623e0b5f0993bbf17dce

This check is failing because it's expecting rid == 107 (or so i think).

But is it needed? Am i right to assume that blob.rid values are specific to each fossil repo clone?

Anyway, i know nearly nothing about the inner workings of fossil, so i'd be grateful for any help here.

Cheers.

Some background info for anyone still reading: i have a number of machines (raspberry PIs, netbooks, desktops) that all have clones of my various fossil repositories.

For those fossil repos that i need to keep synced with git, i use fossil export --git .. storing their fossil and git marks files with the fossil repo as unversioned files hoping that i can use any cloned repo from whatever machine to do incremental updates to git.

(2) By Stephan Beal (stephan) on 2023-07-22 12:09:37 in reply to 1 [link] [source]

But is it needed? Am i right to assume that blob.rid values are specific to each fossil repo clone?

i can't answer that first question but the second one is definitely true. blob.rid should never be used for anything but access to a repository's own data.

(3) By Jerry (jerryko) on 2024-07-28 02:58:36 in reply to 2 [link] [source]

Thanks for the info Stephan, that's what i was hoping. And sorry for writing this so late, i got distracted by some shiny object and lost track of this one..

Here's a diff of the most minimal change that allows for exporting to git from any up-to-date fossil repo. Combined with this neat idea of storing marks as unversioned files, i can use any fossil clone to update git mirrors.

I've tested it with a couple of (previously failing) fossil repositories that used different rid/uuid mappings with success.

It's purposefully written to break style a little in case you wanted to adapt and include it in fossil. Or i can follow proper steps to submit if there's interest.

Index: src/export.c
==================================================================
--- src/export.c
+++ src/export.c
@@ -342,12 +342,16 @@
     return -1;
   }else{
     sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok);
   }
 
-  /* make sure that rid corresponds to UUID */
-  if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){
+  /*
+   * Get rid that corresponds to UUID.
+   * vfile.c:fast_uuid_to_rid() returns 0 if UUID is not found.
+   */
+  mark->rid = fast_uuid_to_rid(mark->uuid);
+  if( mark->rid==0 ){
     free(mark->name);
     fossil_trace("Non-existent SHA-1/SHA-3 in marks file: %s\n", mark->uuid);
     return -1;
   }

(4) By Stephan Beal (stephan) on 2024-08-21 10:56:41 in reply to 3 [link] [source]

I've tested it with a couple of (previously failing) fossil repositories that used different rid/uuid mappings with success.

Before checking this in, can someone familiar with the git export process confirm that the following patch is acceptable? It looks correct to my layman's eyes, but i've no even marginally convenient way to validate it:

Index: src/export.c
==================================================================
--- src/export.c
+++ src/export.c
@@ -310,5 +310,8 @@
     return -1;
   }
-  mark->rid = atoi(&cur_tok[1]);
+  mark->rid = fast_uuid_to_rid(mark->uuid)
+    /* forum post bfb325108171eb8b: we want export to work
+    ** even if the RIDs get re-mapped, e.g. a different clone
+    ** is used. */;
   type_ = cur_tok[0];
   if( type_!='c' && type_!='b' ){
@@ -346,5 +349,5 @@
 
   /* make sure that rid corresponds to UUID */
-  if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){
+  if( !mark->rid ){
     free(mark->name);
     fossil_trace("Non-existent SHA-1/SHA-3 in marks file: %s\n", mark->uuid);

Achtung: there is a code path which calls return create_mark(mark->rid,...) before the if(!mark->rid) check is made, but it's not clear to me whether that check should also be moved up to the top of the function.

(5) By Jerry (jerryko) on 2024-09-25 03:07:44 in reply to 4 [source]

Thanks very much for looking into this issue Stephan.

... but i've no even marginally convenient way to validate it

The smallest public domain repositories i have with divergent rid/uuids are roughly 260k each. I'd be happy to email them to you so you can use them in any way you like?

Here's the shell script i used to find suitable repositories:

(FWIW, i'm pretty chuffed that this gave me an excuse to learn about ATTACH DATABASE ....)

#! /bin/sh

if [ $# -ne 2 ]; then
    echo "$0 <fossil-repo-a> <fossil-repo-b>" >&2
    exit 2
fi

if [ ! -f "$2" ]; then
    exit 3
fi

count=$(${FOSSIL:-/usr/bin/fossil} sqlite -R "$1" <<EOS
ATTACH DATABASE "$2" as repo2;
SELECT COUNT(*)
FROM repository.blob AS a JOIN repo2.blob AS b ON (a.uuid = b.uuid)
WHERE a.rid != b.rid;
EOS
)
if [ "$count" -eq 0 ]; then
    exit 1
else
    echo $count $(stat -c "%s" "$1") $(basename "$1")
    exit 0
fi

Achtung: there is a code path which calls return create_mark(mark->rid,...) ...

Skipping the call to atoi is better and appeals to my sense of efficiency, but that create_mark call you've pointed out seems to require a rid value in order to support older mark files that don't include uuid.

Maybe something like this?

/usr/bin/fossil di
Index: src/export.c
==================================================================
--- src/export.c
+++ src/export.c
@@ -307,20 +307,20 @@
   char type_;
   cur_tok = strtok(line, " \t");
   if( !cur_tok || strlen(cur_tok)<2 ){
     return -1;
   }
-  mark->rid = atoi(&cur_tok[1]);
   type_ = cur_tok[0];
   if( type_!='c' && type_!='b' ){
     /* This is probably a blob mark */
     mark->name = NULL;
     return 0;
   }
 
   cur_tok = strtok(NULL, " \t");
   if( !cur_tok ){
+    mark->rid = atoi(&cur_tok[1]);
     /* This mark was generated by an older version of Fossil and doesn't
     ** include the mark name and uuid.  create_mark() will name the new mark
     ** exactly as it was when exported to git, so that we should have a
     ** valid mapping from git hash<->mark name<->fossil hash. */
     unsigned int mid;
@@ -330,10 +330,11 @@
     else{
       mid = BLOBMARK(mark->rid);
     }
     return create_mark(mark->rid, mark, &mid);
   }else{
+    mark->rid = fast_uuid_to_rid(mark->uuid);
     mark->name = fossil_strdup(cur_tok);
   }
 
   cur_tok = strtok(NULL, "\n");
   if( !cur_tok || (strlen(cur_tok)!=40 && strlen(cur_tok)!=64) ){
@@ -343,11 +344,11 @@
   }else{
     sqlite3_snprintf(sizeof(mark->uuid), mark->uuid, "%s", cur_tok);
   }
 
   /* make sure that rid corresponds to UUID */
-  if( fast_uuid_to_rid(mark->uuid)!=mark->rid ){
+  if( !mark->rid ){
     free(mark->name);
     fossil_trace("Non-existent SHA-1/SHA-3 in marks file: %s\n", mark->uuid);
     return -1;
   }

(6) By Stephan Beal (stephan) on 2024-09-25 04:25:24 in reply to 5 [link] [source]

The smallest public domain repositories i have with divergent rid/uuids are roughly 260k each. I'd be happy to email them to you so you can use them in any way you like?

Ha! To clarify:

... but i've no even marginally convenient way to validate it

was less about availability of git repos to test and more about my complete inability to operate git for anything beyond "clone" and "pull" :/.

Maybe something like this?

i am unfortunately not certain. Though i'm relatively well-versed in most of fossil's internals, i admittedly willfully turn a blind eye to the git-related parts.

i.e. we'll need a genuine fossiler-gitter combo person to validate that fix.

(7) By Stephan Beal (stephan) on 2024-10-11 17:13:11 in reply to 6 [link] [source]

i.e. we'll need a genuine fossiler-gitter combo person to validate that fix.

Ping, in the interest of getting this corrected before the 2.25 release.

(8) By Stephan Beal (stephan) on 2025-02-08 13:16:32 in reply to 6 [link] [source]

i.e. we'll need a genuine fossiler-gitter combo person to validate that fix.

Another ping - this has been flagged as todo in my inbox for ages but i'm not qualified to judge the validity of the patch proposed up-thread.