SRC users: check in, please?

I just released version 1.7 of SRC, Simple Revision Control.

For those of you late to the party, SRC is a simple version control system for directories full of small standalone files like FAQs, scripts in your ~/bin, dotfiles, and so forth – cases where you don’t want multi-file changesets. It’s actually a Python wrapper around RCS (or, optionally, SCCS) but gives you integer sequential version numbers, lockless operation, and a modern low-friction UI modeled on Subversion’s.

With 1.7, I think it’s finished – the last two user-visible features I had planned were SCCS support and DOT visualization, and those are done now.

I believe SRC is now feature-complete for its functional niche. Am I mistaken? Is anything missing? Did I do anything that seems wrong?

I know SRC has had real users since about 0.3. If you are an SRC user, please check in in the comments. Most importantly, tell me if you need any feature it doesn’t have. I’m also curious if the actual use cases are any different than I expected, and I am all agog to know if anyone actually has a use for the SCCS support.

40 thoughts on “SRC users: check in, please?

  1. I don’t use SRC (yet), so feel free to ignore below:

    > M..N (all revisions that are branch ancestors of N and branch successors of M)

    Does it mean strict ancestor only, or is it topological set difference?

    > src log [revision-range] [file…]

    Does it support –graph –color (–oneline)?

    > src diff [revision-range] [file…]

    Does it support –word-diff?

  2. >Does it mean strict ancestor only, or is it topological set difference?

    Strict ancestor. The code walks back from the later revision along its branch and throws an error if it never finds the earlier revision. This works because there are no merges.

    >Does it support –graph –color (–oneline)?

    There is a visualize command that makes a DOT graph of the repo. I guess the equivalent of –oneline is the ‘list’ command. I haven’t thought of any use for color highlighting yet.

    >Does it support –word-diff?

    No.

  3. >> Does it mean strict ancestor only, or is it topological set difference?
    >
    > Strict ancestor. The code walks back from the later revision along its branch and throws an error if it never finds the earlier revision. This works because there are no merges.

    Errr… why adding support for branches, if merging is not supported? RCS has support for merging changes (though not for merge tracking): rcsmerge was one of first 3-way merge algorithms, I think.

    >> Does it support –graph –color (–oneline)?
    >
    > There is a visualize command that makes a DOT graph of the repo. I guess the equivalent of –oneline is the ‘list’ command. I haven’t thought of any use for color highlighting yet.

    I meant here ASCII-art (or Unicode) graph of history, with different color for different branches.

    Something like

    | * 9: second on sidebranch
    * | 8: still on trunk
    * | 7: on trunk
    | * 5: first commit on sidebranch
    |/

  4. > EXPN DOT?

    DOT is a plain text graph description language, that can be rendered e.g. by Graphviz (but is also used as input and output formats for various tools).

    digraph graphname {
    a -> b -> c;
    b -> d;
    a->e->d;
    }

  5. >If you were to design the file format from scratch, instead of using RCS, how would you do it differently?

    I’d use something a lot like fast-import streams or Subversion dump streams – whole-file revisions in a purely textual format. If field experience proved that the repos get too large on disk, I’d apply a couple of obvious optimizations like representing small changes as deltas – but with today’s hardware and costs I suspect this might never happen.

  6. >Errr… why adding support for branches, if merging is not supported?

    Because the RCS file format supports branching but has no representation of branch joins – rcsmerge does content merging but leaves no trace of that operation in the commit graph. Or, to put it exactly, you cannot declare multiple parents for a revision in an RCS file.

    >I meant here ASCII-art (or Unicode) graph of history, with different color for different branches.

    Nope, I don’t have that. Don’t know a simple algorithm for generating it, and suspect anyway that putting a lot of effort into branching support may be overkill for the tool’s use cases.

    I was more interested in practical missing features than theoretical ones, really – what are real users feeling the lack of, if anything?

  7. I like SRC. I think having branching at all might be a bit overkill, but if you have it, even the naive ancestor-finding (which is all that’s possible in rcs) for a standard three-way-merge is useful enough in basic cases – the failure mode when you have no DAG is exploding into conflicts, but I think src could just throw up its hands and refuse to do anything if there’s *any* conflicts, and it would still be a satisfying implementation. I can’t see myself ever making a branch on these kinds of little files, but if I did, I would want to merge it…

    What I don’t like is that it’s somehow broken on my everyday FreeBSD workstation. Do you take bug reports on gitlab or what?

  8. >What I don’t like is that it’s somehow broken on my everyday FreeBSD workstation. Do you take bug reports on gitlab or what?

    I do.

    Check your RCS version – until 1.3 SRC needed RCS 5.7 and on some BSDs they’re still rocking 5.6.

    See the FAQ section on reporting bugs,

  9. Been using it happily since about version 0.5, I think. Got my bash dotfiles and my hosts file on it. I use the Homebrew package; mostly on the CLI but occasionally via Emacs VC mode.

    Does what it says on the tin. This is the kind of project in which ESR shines at, IMHO.

  10. I don’t know if I count as a real user (software is a hobby, and related to my work, although not my job itself). I’ve installed SRC at home as a learning project; my only prior experience with version control is Rational ClearCase (GUI version control) at a previous job. I’ve tried learning git, but don’t do enough collaborative development any more to get much practice, so it’s still pretty alien to me.

    We had two major reasons to use ClearCase instead of just keeping source in someone’s shared directory. First, it ran on its own server, so you could always go back, pick whatever version you like, and make a fresh copy no matter how badly you clobbered your local files. Second, you could see if somebody else had locked a file, which would prevent you from editing it and later having your changes overwritten when they uploaded their modified version.

    After (admittedly not that much) playing with SRC, I’m not sure what problem it actually solves. It saves its data in the same directory as your code, so it doesn’t offer a way to recover from an overly inclusive rm, and it’s designed for a single user so the locking thing isn’t applicable. Is it just that it is more convenient to retrieve an older version from this interface than from an external backup?

  11. > After (admittedly not that much) playing with SRC, I’m not sure what problem it actually solves. It saves its data in the same directory as your code, so it doesn’t offer a way to recover from an overly inclusive rm, and it’s designed for a single user so the locking thing isn’t applicable. Is it just that it is more convenient to retrieve an older version from this interface than from an external backup?

    First, more convenient operations: check older version, retrieve older version, compare two versions, than with external backup; though some of those are AFAIK quite convenient in TimeKeeper-like backup systems.

    Second, you get into habit of planning to work in steps, of committing your work at defined “inch-stones” (instead of saving haphazardly, irregardless whether saved version even makes sense),… and of course browsing history (log / list, annotate / blame / praise if supported).

    Bisecting history for finding regression bugs – though probably not in SRC.

    And of course parallel development, with either locking, merging before commit, merging after commit(s), etc.

  12. >It saves its data in the same directory as your code, so it doesn’t offer a way to recover from an overly inclusive rm

    Both DVCSes and the RCS/SCCS systems SRC is built on the same vulnerability, so it seems a bit unfair to count that is a particular problem of SRC’s.

    >Is it just that it is more convenient to retrieve an older version from this interface than from an external backup?

    That, and there’s independent utility in being able to attach comments to changes.

  13. >Bisecting history for finding regression bugs – though probably not in SRC.

    That’s actually kind of an interesting idea. Wouldn’t be hard to do – but I won’t without some evidence that someone is using SRC for more serious code development than I currently expect.

  14. >Been using it happily since about version 0.5, I think. Got my bash dotfiles and my hosts file on it.

    That is exactly the sort of use case i had in mind!

  15. >This is the kind of project in which ESR shines at, IMHO.

    Hmmm. It didn’t occur to me to wonder, but my wife Cathy is curious what you think that kind is.

  16. SRC 1.0:
    [4]$ src

    The following help topics are available:

    intro — Basic concepts: commits, tags, branches. The form of commands.
    revisions — How to specify ranges of commits to operate on.
    commands — a summary of the commands.
    commit — the commit command: how to commit changes to a file.
    amend — the amend command: editing stored change comments.
    checkout — the checkout command: retrieving historical versions of files.
    cat — the cat command: dumping revisions to standard output.
    status — the status command: more details and unusual status codes.
    log — the log command: dump commit log information to standard output.
    list — the list command: dump commit summaries to standard output.
    diff — the diff command: dump revision differences to standard output.
    fast-export — the fast-export command: export history to other systems.
    fast-import — the fast-import command: import history from other systems.
    ignores — .srcignore files and their uses.

    The ‘help’, ‘rename’, ‘ls’, ‘move’, ‘copy’, and ‘version’ commands are
    completely described in the command summary.

    SRC 1.7:
    [17]$ src
    Traceback (most recent call last):
    File “/usr/local/bin/src”, line 2269, in
    if commandline[0] == vcs.__name__.lower():
    IndexError: list index out of range

  17. I can see a use case for bisecting configuration files: consider your recurrent problems with DNS…

  18. >IndexError: list index out of range

    Oh cripes, what a dumb bug with a trivial fix. Done.

  19. >I can see a use case for bisecting configuration files: consider your recurrent problems with DNS…

    I can, too, but DNS may not be the best example. Getting reproducibility of DNS errors can be a bit slippery even if you have config rollback, alas.

  20. Forgot to add:

    > Second, you get into habit of planning to work in steps, of committing your work at defined “inch-stones” (instead of saving haphazardly, irregardless whether saved version even makes sense),… and of course browsing history (log / list, annotate / blame / praise if supported).

    Which requires the other difference from backup systems (beside savin/committing at stable point), namely description of changes (the commit message).

  21. I used it for a couple small one-shot documentation projects I had when it first came out, but have not had recent use for it.

    Been long enough ago that I do not remember enough of the experience other than it got the job done better than SharePoint. /shiver

  22. >it got the job done better than SharePoint.

    That may constitute damning with faint praise…

  23. Hadn’t thought of that interpretation, but chuckling at the thought now. Was thinking more along the lines of not just setting a low bar, but making the bar out of wire and burying it…

    On a serious note, it was just long enough ago that I don’t trust my recollections to be useful. I do know I saved a bunch of time, even with installing RCS, SRC, the constant switching from IDE (Word, PowerPoint) into a console, rename to “Office worker version control” “standards” and uploading into Sharepoint.

    In summary, I saved a bunch of time using SRC for a use case well outside of its design goal.

  24. @esr –

    I may have uncovered a bug in handling filenames containing the string “–” (that is two hyphens back-to-back, since WordPress will try to prettify it). Version 1.7.

    Have sent you email, including a tarball of test suite, etc.

  25. >Have sent you email, including a tarball of test suite, etc.

    If the bug is what I think it is, you can prevent it by putting a ‘–‘ (two hyphens back-to-back) after your command word and flags and before your file arguments. That token tells the parser ‘range specifications and flags end here, everything after is really truly a filename”.

  26. @esr –

    > If the bug is what I think it is,

    Yup, that fixed it. Thank you!

    /me is embarrassed about the n00b typo in the block comment of his script.

  27. I git-cloned and installed it on a Mac. It wasn’t easy. First I had to get `env python2` to work, which took a lot longer than I expected, then I had to change the makefile to turn off xmllint.

    Questions:

    When you do `src status` is there a way to know which version of the file you’re on? You can checkout an old version and commit. Is it worth reminding the user that they’re on an older version?

    Also when committing you can’t put the “-m $MSG” at the end; you have to add it before the file. Isn’t the convention that the order shouldn’t matter? Does the program mix up the logic of what a command does and how arguments are parsed?

  28. >When you do `src status` is there a way to know which version of the file you’re on?

    No, but src list will tell you that.

    Not a bad idea to add it to the status display though.

    >Also when committing you can’t put the “-m $MSG” at the end; you have to add it before the file. Isn’t the convention that the order shouldn’t matter?

    No, requiring switches like that to precede file arguments is normal – I’m pretty sure git requires it. Writing an argument parser that allows you to mix arguments with switches is possible with custom logic, but getopt(3) and analogues features in other languages don’t support it.

  29. > requiring switches like that to precede file arguments is normal – I’m pretty sure git requires it.

    It doesn’t.

  30. Odd behaviour:

    $ echo “d” >> d.txt; src commit -m “all is well” d.txt
    $ echo “dd” >> d.txt; src commit -m “the plot thickens” d.txt
    $ src status d.txt
    M d.txt
    $ src diff d.txt
    $

    It says that d.txt has been modified but when you do `src diff` there’s nothing.

  31. >It doesn’t.

    Oh? Try operating on a file with a name that starts with ‘-‘; I think you might find out differently. There’s a reason the git commit synopsis includes “[–]”,

    SRC and git are both dealing with the same problem; if you encounter a token beginning with ‘-‘ on a command line, is it an option or an argument? Both solve it the same way; before a “–” such a thing is treated as an option, after it as an argument.

  32. >Odd behaviour:

    Hm, my attempt to speed up status computation in 1.8 seems to have introduced a bug. That ‘M’ status is spuruious, it should be ‘=’. The null diff is correct whwn you have not modified the workfile since the last checkin.

    Working on it…

  33. > Oh? Try operating on a file with a name that starts with ‘-‘; I think you might find out differently. There’s a reason the git commit synopsis includes “[–]”,

    That is not the same thing. In fact, it’s pretty close to the opposite of being the same thing.

    The claim that anonymousman made, which is correct, is that if you have not included “--“, then there’s nothing stopping you from appending options to the end (after the filenames) and having them be interpreted as options. GNU getopt (and thus nearly every program that anyone interacts with on most Linux distributions) supports this, absent either a “+” in the option string or the environment variable POSIXLY_CORRECT.

  34. e.g.: git commit foo.c bar.c baz.c -m “a commit message regarding three files” is a perfectly legal command, and does not refer to a file called “-m”. Yes, you can include –-, if you want to include a file called “-m”, but you don’t have to.

  35. > Both solve it the same way; before a “–” such a thing is treated as an option, after it as an argument.

    Git solves it that way. SRC, if I understand the claims you’re making correctly, solves it the old(er)-fashioned way: before a “–” or any unambiguous filename argument it’s treated as an option, after as an argument. Git also has the added complexity (vs most commands) that some commands (e.g. git diff) accept both revision names and filenames, and the revisions go before the — and the filenames after.

  36. Er, apparently not all git commands are created equal. Git commit works as I describe, but git diff does indeed forbid flags after filenames (but not after revision names)

  37. >Er, apparently not all git commands are created equal. Git commit works as I describe, but git diff does indeed forbid flags after filenames (but not after revision names)

    I’m not surprised. Fully general parsing of the mixed cases is quite tricky.

Leave a Reply

Your email address will not be published. Required fields are marked *