Fossil Forum

Just output current branch name
Login

Just output current branch name

Just output current branch name

(1) By Étienne D. (milouse) on 2018-09-16 16:14:19 [link] [source]

Hi!

Another thing on which I've been working recently, is the ability to quickly discover on which branch we are for the current opened repository. This is something which can be very handy to decorate your shell prompt.

For reference, one way to do it currently is this:

fossil branch list 2>/dev/null | sed -n -r 's/^\*\s+([a-zA-Z0-9_.-]*)$/\1/p'

As you can see, it's not easy to read, nor understand when you are not a shell rookie.

Thus, I've been working around two current fossil command: fossil branch info and fossil info. First thing I do is to make the BRANCH-NAME optional in fossil branch info. Just entering the previous command now output the same thing as fossil branch info CUR-BRANCH. Then I add a new subcommand named fossil branch current, which display only the name of the current branch. Finally, I made the fossil info command react to the --quiet switch to output various quick info (really like the rev-parse git option).

Demo

Before

$ fossil branch info
$ fossil branch current
branch subcommand should be one of: info list ls new
$ fossil info
project-name: Fossil
repository:   /home/milouse/Applis/fossil/../ambre/fossil.fossil
local-root:   /home/milouse/Applis/fossil/
config-db:    /home/milouse/.fossil
project-code: CE59BB9F186226D80E49D1FA2DB29F935CCA0333
checkout:     85411cf88ab45480e5edb5b4b908e8984648ed93 2018-09-05 13:08:03 UTC
parent:       0549dadb416a64933a5202dbab505f82e8527737 2018-09-05 13:06:08 UTC
tags:         current-branch-info
comment:      React to the quiet switch in fossil info (user: milouse)
check-ins:    11842
$ fossil info --quiet
project-name: Fossil
repository:   /home/milouse/Applis/fossil/../ambre/fossil.fossil
local-root:   /home/milouse/Applis/fossil/
config-db:    /home/milouse/.fossil
project-code: CE59BB9F186226D80E49D1FA2DB29F935CCA0333
checkout:     85411cf88ab45480e5edb5b4b908e8984648ed93 2018-09-05 13:08:03 UTC
parent:       0549dadb416a64933a5202dbab505f82e8527737 2018-09-05 13:06:08 UTC
tags:         current-branch-info
comment:      React to the quiet switch in fossil info (user: milouse)
check-ins:    11842

Now

$ ./fossil branch info
current-branch-info: open as of 2018-09-05 13:08:03 on 85411cf88ab45480
$ ./fossil branch current
current-branch-info
$ ./fossil info
project-name: Fossil
repository:   /home/milouse/Applis/fossil/../ambre/fossil.fossil
local-root:   /home/milouse/Applis/fossil/
config-db:    /home/milouse/.fossil
project-code: CE59BB9F186226D80E49D1FA2DB29F935CCA0333
checkout:     85411cf88ab45480e5edb5b4b908e8984648ed93 2018-09-05 13:08:03 UTC
parent:       0549dadb416a64933a5202dbab505f82e8527737 2018-09-05 13:06:08 UTC
tags:         current-branch-info
comment:      React to the quiet switch in fossil info (user: milouse)
check-ins:    11842
$ ./fossil info --quiet
85411cf88ab45480e5edb5b4b908e8984648ed9342b23cd521cf4f251ea5d137
$ ./fossil info --quiet --short
85411cf88a
$ ./fossil info --quiet --symbolic
current-branch-info

As always, what do you think of it? I think it could be very helpful in script context, to directly get some useful value, without having to parse fossil output through sed or grep. The code is available for review on the current-branch-info branch of my fossil clone.

Good evening,

(2) By Warren Young (wyoung) on 2018-09-16 20:49:30 in reply to 1 [link] [source]

This sounds like it's mainly useful when you switch branches within a single checkout directory, as the Git people do, since repo == checkout under Git unless you use their git-worktree hack.

My Fossil checkout trees look something like this:

  cd ~/projects
  mkdir -p reponame/trunk
  cd reponame/trunk
  fossil open ~/museum/reponame.fossil
  mkdir ../working-branch
  cd ../working-branch
  fossil open ~/museum/reponame.fossil working-branch

I've been known to have a dozen or so open branches for a single project that way. My shell's current working directory is the branch name, so I already have the branch name in my shell prompt. It's also in my terminal window's title via the Xterm title setting feature, since most OSes update that on cd these days.

Occasionally I will switch to a different branch within one of the checkout directories, so that the directory name doesn't match the current working branch name, usually via fossil ci --branch in the trunk checkout directory. If I then choose not to fossil up trunk from that directory and check the new branch out in a separate checkout directory, I might later forget that I'm no longer on trunk in that checkout tree. This usually happens for branches intended to be very short-lived, usually within a working day, but sometimes such a branch can't be merged back to trunk before I forget that I'm no longer on trunk.

When that rare case happens, I get reminded which branch I'm on by EDITOR=vim fossil ci, which gives the branch name in the tags list of the canned text at the bottom of the commit message. I've neglected to pay attention to that a few times, and ended up checking something in on the wrong branch, so I've just gotten into the habit of checking the tags list in the checkin message before saving the commit message.

With this scheme, you switch between long-lived branches via cd, not via fossil up. Not only does that have the benefit of keeping the branch name in the shell prompt and xterm title, it means build artifacts aren't invalidated on each branch switch, keeping build times low.

So, am I right in my guess that you're running Fossil in a single-checkout mode, and thus find yourself losing track of which branch you're in at any one moment?

(3) By Warren Young (wyoung) on 2018-09-16 21:16:08 in reply to 2 [link] [source]

The current branch name is also in the fossil stat output, for whatever that's worth. I find myself giving that command fairly often to get that and other information about the current checkout.

(4) By Étienne D. (milouse) on 2018-09-17 08:37:28 in reply to 2 [link] [source]

Hi!

Yes, you are totally right, I'm running fossil in a single-checkout mode. I don't even know we can do otherwise. I thought a fossil repository could only be opened once.

Your workflow is very interesting, and I'm sad I didn't read about it sooner. I may be wrong, but I think it is not published in the documentation. I think it should be published as an appendix of the branching page to let newcomers discover a new valuable workflow. Is your workflow the standard fossil approach or just a process you follow personally?

By the way, in the git world nothing blocks you from having the same workflow than you, with one local folder by git branch for the same remote repository. I often use that too to avoid stashing every time I need to quickly move from the develop branch to the stable one.

On the other hand, even your process is not branch-mess-proof. Nothing in the current fossil behavior blocks you from updating to another branch at any time or, like you said, ci --branch. That is to say, someone with less skills than you may do thing, leading his multi-checkout mode folder hierarchy to a chaos, where branch-named folder point in fact to something else. As the current folder name is not controlled by fossil itself, I think its a little dangerous to rely on it to quickly check on which branch you really are.

(5) By Stephan Beal (stephan) on 2018-09-17 08:59:24 in reply to 4 [link] [source]

"By the way, in the git world nothing blocks you from having the same workflow than you..."

With one subtle difference: in fossil, you can open each clone (repository file) any number of times, and all checkouts work with that same repository file. That means, for example, when you push/sync/commit to anyone of those copies, it works on the same repository copy being used by all other checkouts. In git, each opened copy is a 100% standalone clone of the upstream repository. This means, for example, that if Warren commits (in fossil) something in his branch-X checkout, those changes are immediately visible in the repository being used by his branch-Y and branch-Z checkouts. To actually include those those changes into his other checkouts, he would still need to do "update" (or similar) in each branch, but "timeline" would show those changes, without an update, regardless of which branch-directory it was run from.

One interesting side-effect of this is that Warren can work 100% offline (e.g. on a plane on his way to the hypothetical Annual International Fossil Conference in Geneva, Switzerland) and still update/merge between his opened branches, whereas git cannot do this (to the best of my knowledge) because each checkout is a standalone copy using its own clone of the central repository. (Granted, one could set up a local git server to do that with, but that would require extra setup which fossil doesn't need for that (admittedly unusual) use case.)

(6) By Warren Young (wyoung) on 2018-09-17 09:05:46 in reply to 4 [link] [source]

I think [your workflow] is not published in the documentation.

I didn't invent it, so I must have read it somewhere. A bit of searching turns up two other places the practice is recommended:

I think it should be published as an appendix of the branching page

That document seems to be more about the fundamentals of branching rather than a day-to-day usage guide.

It might make more sense in the "Checking Out A Local Tree" section of the quickstart document, but I worry that it complicates a discussion that purposefully leaves out much of the detail involved in real-world Fossil usage.

I've got the text already written: I make it part of the "hacker's guide" for my various public FOSS projects. Here's one version.

Anyone else want to offer an opinion on where I should stick it? Be nice. :)

in the git world nothing blocks you from having the same workflow than you

Yes, as I said, Git offers the git-worktree hack. I characterize it that way because of a number of known problems caused by using it, which you can discover with obvious web searches.

Git of course will also let you make multiple independent clones, but that wastes a lot of disk space compared to either git-worktree or the Fossil scheme of separate clones and checkouts.

even your process is not branch-mess-proof

At some point, you do have to rely on the human to know what's going on, yes. :)

someone with less skills than you may...

I'm no paragon of Fossil usage prowess. As I said above, I've checked things into the wrong branch several times.

The main thing I question is whether someone who is prone to doing that more than I am would remember to look at their command prompt to see the branch name, when they've already ignored the tags list in the checkin message, the output of fossil stat, etc.

It's difficult to fix "oblivious." I'm not sure the condition can be solved with technical solutions.

(7) By anonymous on 2018-09-17 16:31:40 in reply to 5 [link] [source]

Another advantage to directory-per-branch approach is when dealing with rather large projects that take considerable time to build.

Swtiching branches in-place in such a case would lead to rebuilds due to timestamp differences between sources and objects.

Even with Git workflow in such cases it's reasonable to keep active branches checked-out in separate directories; resp. pushes to upstream facilitate local updates. Of course, there's some overhead with this vs. Fossil's clone repo + multiple work-dirs.

As for the current branch in general, I find 'fossil status' quite enough -- the current branch appears first in the tag-list. I run 'status' anytime I get back to working on the contents, so it's kind of multi-platform habit. Said this, 'status' command is somewhat slower than 'branch' as it needs to check for changes. But let the hardware absorb the overhead, as in practice it's not perceivable ...unless your big project is on a USB flash-dirve.

(8) By Richard Hipp (drh) on 2018-09-17 16:50:14 in reply to 4 [link] [source]

your process is not branch-mess-proof

Yes, it is possible to check things into the wrong branch. I've done that myself, more than once.

At one point, I tried to impose a commit-checklist on some of the projects I manage. The checklist was a short list of things to verify before doing a commit. This checklist contained bullets like the following:

  • Run "fossil diff" and verify no stray changes or surplus whitespace
  • Run "fossil extra" to verify no unmanaged files need to be added
  • Run "fossil status" to verify the commit is going into the correct branch
  • Verify that the system clock is at least approximately correct

There were other application-specific requirements and testing requirements prior to commits to trunk.

However, I allowed checkin discipline to grow lax, and so nobody follows the checkin checklist anymore.

But maybe the checkin checklist could be automated somehow, as a kind of pre-commit hook. Of course, a user could bypass the automation. The point is not to force users to do the right thing, only to make it convenient for them to do the right thing. Possible implementations:

  1. Pop-up a separate GUI program containing the checklist. Perhaps this separate GUI is a wish script (such as the script that implements the --tk option to diff) and is thus cross-platform.

  2. Prompt the user with several y/n questions on the command line: "Have you run 'fossil diff'?", "Have you run 'fossil extra'?", and so forth.

  3. Put the checklist in comments in the commit message and require the user to check boxes on that checklist to prevent the commit message from being rejected.

Key factors here are that each project will want to have a different checkin checklist (including the option of no checklist at all) and that checklist will likely evolve over time. So the checklist should be synced. It could be either a special managed file or "unversioned" content, I suppose.

(9) By Étienne D. (milouse) on 2018-09-17 18:15:21 in reply to 8 [link] [source]

Something interesting in the two previous answer (from @drh and @wyoung) is that you rely on the user to enter commit message inside his/her editor. A lot of people will instead directly use the -m switch and thus never see any warning or checklist :(

However, I do like the possibility to run pre-commit check. I think a good way to do it is just to delegate it to some scripts stored inside the special .fossil-settings folder, like git does with its various hook. That way fossil doesn't have to bother with what to do exactly (maybe just providing a sample script, which asks the user to do some check before actually committing), but just lookup in a specific folder if a script exists or not, and execute it. I'll try to work on it to see what could be done on this side.

On the other hand, I would like to come back to the beginning of the debate. It evolves to a « pre commit check » debate, but my first proposal was just about having a simple way to retrieve the current branch name (or the last check-in hash) of the current opened repository, at any time. It seems to be a not so useful feature after all?

(10) By anonymous on 2018-09-17 18:33:22 in reply to 8 [link] [source]

I'm not sure if a check-list approach would necessarily lead to better adherence to the practices. Ultimately it becomes up to user's eyeballing ability/patience to confirm the "correct" diffs.

If anything that matters for the overall project, it has to be the build quality (that is a main-line commit should be buildable in a clean checkout) and some automated checks based on the project requirements (style checks, unit tests etc.). That's usually a build-server's task.

As we all know, regular prompts very soon may feel like an annoying friction and may in fact become detrimental as users hastingly hit OK through just to be done with the commit.

(11) By Joel Dueck (joeld) on 2018-09-17 18:35:03 in reply to 1 [link] [source]

I took a look at the fossil plugin on my ZSH shell, and its method of getting the current branch name is just a bit simpler:

fossil branch 2>&1 | grep "* " | sed 's/* //g'

(12) By anonymous on 2018-09-18 01:20:44 in reply to 11 [link] [source]

Even simpler:

fossil branch | sed -ne 's/^* //p'

-n prevents printing lines by default. The p at the end of the substitute command says print if a substitution was made so only the line starting with "* " is printed. Anchoring to the beginning of line makes it a tad faster.

Also I don't think there is any need to redirect stderr. The output of the branch command is sent to stdout. If there is an error during the branch command you probably want to see it (however I am not sure what happens to stderr if run as part of a prompt string).

(13) By Warren Young (wyoung) on 2018-09-18 10:21:32 in reply to 12 [link] [source]

Nicely done. It even works on both BSD and GNU sed, which is not a given, unfortunately.

My only quibble is that it depends on the branch to still be open. If you're in a checkout for a closed branch, you'll get an empty string back, so whatever you're feeding this to should probably have an explicit coping strategy for that case.

(14) By mattwell on 2018-09-18 14:59:37 in reply to 9 [link] [source]

Being able to directly query the branch would be very useful. we have a dozen scripts floating around here which do variations on the sed silliness. None of them are robust against the fact that you can put '* foo' in as a branch and when you have dozens of developers hammering on fossil repos day in day out it is only a matter of time before someone accidentally (or purposefully) does that. A programmatically friendly, quiet, simple, unambiguous current branch query is a reasonable request IMHO.

> fossil currentbranch
trunk
>
In bash:
mybranch=$(fossil currentbranch)
To the devs, have a heart, please consider this request :) , some of us have to wrap fossil with methodology and automation.

Aside: The safest way to get this info is with the json interface:

bash-3.00$ fossil json branch list |grep 'current":'|cut -d\" -f4
* abc*def
Note that this is not "json aware" and thus potentially still brittle.

The full json output is:

fossil json branch list
{
        "fossil":"62dcb00e68b792063f2067b6087befddf6fd89d0",
        "timestamp":1537282415,
        "command":"branch/list",
        "procTimeUs":0,
        "procTimeMs":0,
        "payload":{
                "range":"open",
                "current":"* abc*def",
                "branches":[
                        "* abc*def",
                        "trunk"
                ]
        }
}

(15) By Joel Dueck (joeld) on 2018-09-18 15:39:42 in reply to 12 [link] [source]

Also I don't think there is any need to redirect stderr.

This was in the context of a shell plugin that puts info about the current directory in the shell prompt. I am guessing it does this to account for the possibility that the current directory is not part of a fossil checkout.

(16) By Richard Hipp (drh) on 2018-09-18 15:51:04 in reply to 14 [link] [source]

The "fossil branch current" command is now available on trunk.

(17) By Stephan Beal (stephan) on 2018-09-18 17:52:23 in reply to 14 [link] [source]

fossil json branch list

is/was segfaulting at shutdown due to a missing db_finalize(). i just checked in a fix for that:

https://fossil-scm.org/fossil/info/e45789ee8319f9d3

(i really need to break down and learn markdown syntax someday.)

(18) By Warren Young (wyetr) on 2018-09-18 21:37:26 in reply to 14 [link] [source]

this is not "json aware" and thus potentially still brittle.

Use jq:

  $ fossil json branch list | jq -r '.payload.current'

(19) By Étienne D. (milouse) on 2018-09-19 07:23:54 in reply to 16 [source]

Oh, thank you very much for your understanding! It will help a lot in external scripts.