Fossil Forum

Please add some command-line sanity - implementing git log -p
Login

Please add some command-line sanity - implementing git log -p

Please add some command-line sanity - implementing git log -p

(1) By xerusf on 2023-11-18 11:13:58 [link] [source]

Trying to replicate git log -p within fossil has proven quite challenging because the default behaviour of fossil is unsuitable to command-line processing in so many regards, and CLI helpers are my bread and butter. First of all, I would have expected fossil timeline to default to a more machine-readable format like --oneline when piped. Well, I can accept this as a design decision to not have different behavior for such cases.

But then, why is the 'line limit reached' line output to stdout rather than stderr with no option of hiding it, forcing me to add another step to cut if off?

And to replicate git log -p including paths, I now need to use a combination of fossil timeline and fossil finfo and I don't understand why these have to be separate - having all options of both available in one just like in git log seems very reasonable, because in the end finfo is just a timeline filtered to changes to a filename. Nevermind, found timeline -p and their differences.

And for some reason, fossil timeline --format %H puts an empty line between each hash?

So this is what I ended up with, feel free to replace bat with your pager of choice ;)

flp() {
    case "$1" in
    (""|-*) true;;
    (*) filepath="$1"; shift;;
    esac
    local prev
    fossil timeline --format=%H -p "$filepath" "$@" | head -n -1 | while read -r revision; do
        test -n "$revision" || continue
        test -z "$prev" || fossil diff --from "$revision" --to "$prev" "$filepath"
        printf "\033[7m%-${COLUMNS}s\033[27m" "   Rev:$revision" | sed 's/ /─/g'
        prev="$revision"
    done | bat --plain --language diff
}

(2.3) By Warren Young (wyoung) on 2023-11-18 21:21:41 edited from 2.2 in reply to 1 [source]

Trying to replicate git log -p…

Are you doing that out of inculcated habit or because that's the only way to achieve your desired end? Trawling the log is necessary in Git because it has no indexed lookups into the hash tree like Fossil does. There may be a better way to get what you want than emulating Git atop Fossil.

--oneline when piped

How then would you disable that mode when the pipe target is something like less? Don't you then need --multiline or --no-oneline to turn that default back off when its auto-guesser turns out to be wrong?

This sort of thinking is how Git's overcomplicated CLI accreted.

in the end finfo is just a timeline filtered to changes to a filename.

Not even close. Compare the SQL used to generate /finfo web output to that backing the timeline command.

EDIT: The CLI version of finfo cannot currently do this rename back-tracing, and if it could, your use of timeline to get the list of historical hashes for commits mentioning the file would still leave you without that back-tracing. This shows that finfo and timeline aren't the same thing at a fundamental level.

Fossil is not a reimplementation of Git but with all its subcommands and options pointlessly misspelled.

(3) By xerusf on 2023-11-18 19:31:27 in reply to 2.2 [link] [source]

Fossil is not a reimplementation of Git but with all its subcommands and options pointlessly misspelled.

I know, but as a longtime git user I am trying to accommodate as I think fossil might be a better fit for many projects of mine in the long run :)

I replicate git log -p because I like to see how a file changed over commits. This helped me to identify which states of it to shun to remove some credentials from the history. And sometimes I like to just make a full-text search through the diff of all commits to find something - I like my text-based interfaces :)

How then would you disable that mode when the pipe target is something like less? Don't you then need --multiline or --no-oneline to turn that default back off when its auto-guesser turns out to be wrong?

Actually there is a simple way that works universally on every command I tried so far: Prefix the command with unbuffer, this makes the command think it runs interactively ;)

(4.1) By Warren Young (wyoung) on 2023-11-18 21:18:50 edited from 4.0 in reply to 3 [link] [source]

Before I begin, I believe your "| head -n -1" is a remnant of earlier testing that should be removed to replicate git log -p.

With that in mind, I believe this should prove inspiring, if not "finished":

fossil timeline --format='%h' --path "$path" --limit 0 |
  sed '/^$/d' |
  while read checkin
  do
    fossil diff --checkin "$checkin" "$path"
    printf "\033[7m%-${COLUMNS}s\033[27m" "   Rev:$checkin" | sed 's/ /─/g'
    prev="$checkin"
done | $PAGER

Every difference is for a purpose:

  • "filepath" vs "path", I prefer to name arguments after the flags they affect
  • filter blank lines in bulk with sed rather than test for nonexistence of the hash
  • "--limit 0" gets you around one of your initial complaints
  • abbreviated hashes suffice
  • wrap the pipeline to avoid overlong lines
  • "checkin" is a more Fossil term; see also…
  • use diff's --checkin flag instead of --from + --to $prev
  • use the common PAGER environment variable rather than hard-code it
  • EDIT: drop the "$@" bit; the fossil timeline command is producing parsed output that should not be modified by the remaining un-shifted function parameters

(5) By Daniel Dumitriu (danield) on 2023-11-20 19:01:13 in reply to 1 [link] [source]

And for some reason, fossil timeline --format %H puts an empty line between each hash?

This has just been fixed on trunk.