Fossil Forum

Comments about libfossil, and "generalized fossil"
Login

Comments about libfossil, and "generalized fossil"

Comments about libfossil, and "generalized fossil"

(1) By anonymous on 2021-11-10 21:58:14 [link] [source]

I have tried libfossil, and it looks good, but I have the following comments:

  1. Some things seems to be unstable.

  2. It uses the deprecated sqlite3_trace function. (I put in a function that does nothing, in my example code, to get it to compile.)

  3. It doesn't have the possibility to open as read only, although apparently it is supposed to but isn't. (I worked around this by adding a VFS shim.)

  4. The fsl_buffer object seems a good idea for handling this (at least when you do not need to mix different kinds of memory allocations including static allocations).

  5. Although most things are documented, it is difficult to find things due to having to skip to different parts to try to find what you are looking for. However, once it is found, it seems to work.

  6. It uses C99, while I generally use GNU89. However, the program below compiles and works fine in GNU99 mode.

  7. I would use the GNU fopencookie function for stream objects, since I find this very useful. (I had started writing my own code which is in the public domain and doesn't use libfossil, which does use this, it makes a writable stream object to write data and then you can set a echo stream that anything written will also be copied to, and when closed, the hash of the data that was written is computed and written to a buffer that you originally specified.)

  8. It doesn't implement the protocol, but I think that is supposed to be a much later feature anyways. (I would have it use callback functions to determine permissions and possibly other hooks.) (Although the existing Fossil can be used, it also exposes other interfaces than /xfer and /raw even if you want to disable them, and doesn't have callbacks for other things that you might want to do with it; both for server and client side.)

  9. Another feature I think might be wanted is the mode for the "generalized fossil" format, where any deck can contain any cards (and can omit any cards), and optionally digitally signed; only is required to have exactly one Z card, with the other cards being in the correct order with no duplicate cards. Topological sorting can be used to find which artifact is considered to be newer than another one, using the D cards (if any are present) to break ties.

I also wrote a simple program using it, shown below. (Some of the comments above are applied to this program, for comparison.) (It doesn't do everything perfectly, but I did it just for testing.) The program works OK.

static fsl_cx*fcx;
static sqlite3_vfs*basevfs;
static sqlite3_vfs newvfs;

void*sqlite3_trace(sqlite3*db,void(*cb)(void*,const char*),void*usr) {
  return 0;
}

static int out_func(void*state,void const*src,fsl_size_t n) {
  fwrite(src,1,n,stdout);
  return 0;
}

static int my_vfs_open(sqlite3_vfs*vfs,const char*zname,sqlite3_file*file,int flags,int*outflags) {
  return basevfs->xOpen(basevfs,zname,file,1|flags&~6,outflags);
}

static int timeline_callback(fsl_stmt*st,void*state) {
  printf("%s [%s] %s\n",fsl_stmt_g_text(st,0,0),fsl_stmt_g_text(st,1,0),fsl_stmt_g_text(st,2,0));
  return 0;
}

int main(int argc,char**argv) {
  fsl_buffer buf=fsl_buffer_empty;
  fsl_id_t rid;
  if(argc<2) errx(1,"Too few arguments");
  sqlite3_initialize();
  basevfs=sqlite3_vfs_find(0);
  memcpy(&newvfs,basevfs,sizeof(sqlite3_vfs));
  newvfs.pNext=0;
  newvfs.zName="readonlyvfs";
  newvfs.xOpen=my_vfs_open;
  sqlite3_vfs_register(&newvfs,1);
  if(fsl_cx_init(&fcx,0)) errx(1,"Cannot initialize libfossil");
  if(fsl_repo_open(fcx,argv[1])) errx(1,"Cannot open repository");
  if(argc<3) {
    fsl_stmt st=fsl_stmt_empty;
    if(fsl_cx_prepare(fcx,&st,"select datetime(mtime),(select uuid from blob where rid=objid),comment from event where type='ci' order by mtime desc limit 50;")) {
      errx(1,"SQL error: %s",fsl_cx_err_get_e(fcx)->msg.mem);
    }
    fsl_stmt_each(&st,timeline_callback,0);
    fsl_stmt_finalize(&st);
    return 0;
  }
  if(fsl_sym_to_rid(fcx,argv[2],FSL_SATYPE_ANY,&rid)) errx(1,"Cannot find artifact '%s'",argv[2]);
  if(fsl_content_get(fcx,rid,&buf)) errx(1,"Cannot get content from database");
  if(argc>3) {
    fsl_buffer buf2=fsl_buffer_empty;
    fsl_diff_builder*dif=0;
    fsl_diff_opt opt={0};
    if(fsl_sym_to_rid(fcx,argv[3],FSL_SATYPE_ANY,&rid)) errx(1,"Cannot find artifact '%s'",argv[3]);
    if(fsl_content_get(fcx,rid,&buf2)) errx(1,"Cannot get content from database");
    if(fsl_diff_builder_factory(FSL_DIFF_BUILDER_UNIFIED_TEXT,&dif)) errx(1,"Cannot initialize diff builder");
    opt.diffFlags=FSL_DIFF2_LINE_NUMBERS|FSL_DIFF2_NOINDEX;
    opt.contextLines=5;
    opt.columnWidth=0;
    opt.hashLHS=argv[2];
    opt.hashRHS=argv[3];
    opt.out=out_func;
    dif->opt=&opt;
    if(fsl_diff_v2(&buf,&buf2,dif)) errx(1,"Cannot perform diff");
  } else {
    fwrite(buf.mem,buf.used,1,stdout);
  }
  return 0;
}

Later, I might also try to make an alternative HTML-based interface for Fossil using libfossil, and possibly also Gemini, etc.

(2) By Stephan Beal (stephan) on 2021-11-11 05:31:47 in reply to 1 [link] [source]

I have tried libfossil, and it looks good, but I have the following comments:

We have a separate form for libfossil but it's currently read-only for the general public. If you care to contact me off-list (contact detailsa are at https://wanderinghorse.net/home/stephan/) i will be happy to set up you a forum account (with a fake identity if you prefer, but anonymous posting to that forum probably won't be permitted until after the project reaches "1.0").

Some things seems to be unstable.

FWIW, i use the libf tools every day for most of my fossil work and am not aware of any instability other than API instability - the APIs currently have no stability guarantees (and they won't until the library approaches something which might be called "1.0").

It uses the deprecated sqlite3_trace function. (I put in a function that does nothing, in my example code, to get it to compile.)

Because that part of the code was written before sqlite3_trace() was deprecated. It will be fixed when it breaks or when someone bothered enough by that creates a patch. Until then, "it works, so don't fix it."

It doesn't have the possibility to open as read only, although apparently it is supposed to but isn't. (I worked around this by adding a VFS shim.)

It has never intended to permit read-only opening of a fossil repository. The db layer itself permits read-only opening of sqlite dbs, but there has never been any effort put into supporting read-only fossil repositories. Patches are happily considered but it's not a use case i ever have to deal with so it's highly unlikely that i'll expend any effort on adding such a capability myself.

It uses C99, while I generally use GNU89.

The library code aims to be as platform-portable as possible, and GNU89 is specifically tied to one brand of compiler. It was strictly C89 for a long time, but now that MS compilers finally support C99, it's time to move on.

I would use the GNU fopencookie function for stream objects, since I find this very useful.

Standard APIs are, for this library, always preferred. Platform-specific code is only used where it's absolutely necessary for a required feature.

It doesn't implement the protocol, but I think that is supposed to be a much later feature anyways.

Presumably you mean the sync protocol. That's one of the remaining major TODOs. There is no intent to match every single fossil feature, only to provide the underlying bits necessary for other apps to do so. Certain fossil features, e.g. full ticketing support and HTML-related components (e.g. wiki parsing and rendering), are currently nowhere on the library's roadmap.

Another feature I think might be wanted is the mode for the "generalized fossil" format, where any deck can contain any cards (and can omit any cards), and optionally digitally signed;

In terms of artifacts, the library aims only to support those defined by fossil. Any control artifacts the library creates have to be parseable by fossil. If they're not, that's a bug. If someone wants to fork/extend it to support their own (inherently incompatible) selection of artifacts, that's fine by me but such support won't be part of the core library. Compatibility with fossil is an non-negotiable requirement for me. (That said, i would genuinely like to see what someone could create via such a fork. There's no harm in experimenting, but this library's purpose is to provide alternate ways to access and use fossil-compatible repositories.)

(3) By anonymous on 2021-11-11 06:53:58 in reply to 2 [link] [source]

FWIW, i use the libf tools every day for most of my fossil work and am not aware of any instability other than API instability - the APIs currently have no stability guarantees

I do actually mean API instabilities. Perhaps I should have been more clear.

It has never intended to permit read-only opening of a fossil repository. ... Patches are happily considered but it's not a use case i ever have to deal with so it's highly unlikely that i'll expend any effort on adding such a capability myself.

The documentation seems to mention read-only modes; maybe I misunderstood.

Still, at least for now I can use the VFS shim. (The reason I wanted this was to avoid unexpected changes to the repository due to not knowing quite everything that libfossil might do, even though I am not trying to write to the repository.)

GNU89 is specifically tied to one brand of compiler

It isn't; both clang and GCC support the GNU C, and a few other compilers support some of the GNU features, too.

However, you would be right that not all compilers do, so it is still a valid point.

(5) By jamsek on 2021-11-13 03:12:48 in reply to 3 [link] [source]

The reason I wanted this was to avoid unexpected changes to the repository due to not knowing quite everything that libfossil might do, even though I am not trying to write to the repository

FWIW, fncmisref till recently was read-only, and despite reading just
about every possible aspect of the checkout, repository, and global
databases, we never had an accidental write. The APIs are really
well-documented, and routines are explicitly named so it'd be difficult
to produce an unexpected change. That said, if there are any specific
lib routines you'd like to provide a readonly flag, I'm sure patches
would be thoughtfully considered. Stephan is easily approachable and
super helpful; he has always welcomed my (sane and not so sane) queries,
so I'm sure yours would likewise be well-received.

misref: https://fnc.bsdbox.org


  1. ^ a b Misreference

(4) By anonymous on 2021-11-13 02:29:16 in reply to 1 [source]

While trying to write a alternative HTML-based interface for a fossil repository, I found that the spech_urldecode function doesn't seems to check that a percentage sign is really followed by two more characters, and may read past the null terminator. (Another problem seems to be it doesn't include the way to limit the amount of input or output from this format.) Perhaps this should be corrected, please. So, I wrote my own URL decoding function, instead.

(6) By Stephan Beal (stephan) on 2021-11-13 03:35:10 in reply to 4 [link] [source]

While trying to write a alternative HTML-based interface for a fossil repository, I found that the spech_urldecode function doesn't seems to check that a percentage sign is really followed by two more characters, and may read past the null terminator.

Thank you for that report. i'll take a look in just a few moments. That code was originally ported from fossil so i'll double-check that impl as well (but the port was years ago - it's possible that that's since been fixed in fossil).

If you would, please make further libfossil-specific posts to:

https://fossil.wanderinghorse.net/r/libfossil-forum

i have just enabled anonymous posts there, but there is one significant caveat: sending of notifications from my hoster has highly unpredictable delays. Sometimes it's 10 minutes, sometimes 2 hours.

Though libfossil is ostensibly related to fossil, it is a separate project and this forum is not the place for extended discussions about it.