Fossil Forum


Commit changes by fossil web GUI

By peter on 2018-09-18 19:44:24 [link]


I am experimenting with recent (2018-09-14) tcl enabled trunk version of fossil and repository having tcl=1, th1-docs=1 and th1-hooks=1 set.

For my colleagues with no way to get shell access I like to provide means to commit changes with commit description message.

In my crude POC, on /tktsetup_com page (TH1 script that initializes variables prior to generating any of the ticket view, edit, or creation pages) I prepend default script with:

tclEval {exec sh -c "/home/usr/repos/wrk/ &" };

In a root of open checkout I place script with:

## external scrip to addremove files and possibly commit user originating message
echo `date`   >> /home/usr/repos/wrk/operationlog.log
echo $@       >> /home/usr/repos/wrk/operationlog.log
echo $1       >> /home/usr/repos/wrk/operationlog.log
cd /home/usr/repos/wrk/ && fossil addremove     >> /home/usr/repos/wrk/operationlog.log
cd /home/usr/repos/wrk/ && fossil commit -m 'commit message'  >> /home/usr/repos/wrk/operationlog.log

Now whenever I click on /ticket link it addremove all changes in checkout and commits with static "commit message" message.

I would greatly appreciate suggestions on:

  • how to present user with form to describe current changes in checkout and transfer this message to commit script/command
  • what would be better place/approach to hook execution of external script for addremove and commit action
  • any other ideas how to accomplish this better, perhaps by fossil only means (no external script)


By andygoth on 2018-09-22 00:39:28 [link]

Thank you for bringing this up. I have so many ideas on this subject. The central point is to extend the concept of the "ckout" version recognized by /doc and have it show up as a fake version in the timeline against which diffs can be performed. When the "ckout" version is selected using /info, not only will it show all the changes in the checked-out version relative to its baseline, but it will also provide extra buttons to actually check it in, as well as to revert it or add new files or whatever else.

By wyoung on 2018-09-22 01:17:56

This request has come up several times before, so apparently several people want it.

It's sensible, too, no more odd than posting to a blog, forum, or wiki. Fossil is already most of the way to allowing it. It'd probably be easier to do than this forum feature.

Doing it in terms of ckout is a good plan.

I think all we want here is someone with the itch to scratch it. I think the main difficulty in finding the feature's implementor is that the wishes are coming largely from the "I don't write software" camp.

By peter on 2018-10-23 03:57:03 [link]

Thank you all for the suggestions. At the moment we are using following th1 form to execute commits by fossil web GUI. It is inspired by test/fileStat.th1 script.

To use it there must be TCL enabled fossil binary, TCL enabled open fossil repository with form commited as e.g. commit-form.th1 file.

Commit (and preceding addremove action) is executed by invocation of repository /doc/tip/commit-form.th1 link, filling the message and pressing Commit button.

Beside improvement suggestions I would appreciate hints on how to capture results of child process execution from asynchronous execution as exec fossil command &. In the script it is this line:

set ciasync [eval [getFossilCommand "" "$TCLuser" ci -m $myCommitMsg ] &];

$ciasync is now set to child's PID only, I would like to capture full execution output.


commit-form.th1 file bellow.

  proc doSomeTclSetup {} {
    # NOTE: Copy repository file name, username and full fossil executable
    # to the Tcl interpreter.  
    tclInvoke set TCLrepository [repository]
    tclInvoke set TCLuser [globalState user]
    tclInvoke set TCLexecutable [globalState executable]

    # NOTE: Create some procedures in the Tcl interpreter to perform
    #       useful operations.  This could also do things like load
    #       packages, etc.
    tclEval {
      # NOTE: Returns an [exec] command for Fossil, using the provided
      #       sub-command and arguments, suitable for use with [eval]
      #       or [catch].
      proc getFossilCommand { TCLrepository user args } {
        global env

        lappend result exec [info nameofexecutable]

        if {[info exists env(GATEWAY_INTERFACE)]} then {
          # NOTE: This option is required when calling
          #       out to the Fossil executable from a
          #       CGI process.
          lappend result -nocgi

        eval lappend result $args

        if {[string length $TCLrepository] > 0} then {
          # NOTE: This is almost certainly required
          #       when calling out to the Fossil
          #       executable on the server because
          #       there is almost never an open
          #       checkout.
          lappend result -R $TCLrepository

        if {[string length $user] > 0} then {
          lappend result -U $user
          # DBG:prints exec string
          # th1Eval [list html $result<br>]
        return $result

  proc getCheckoutDir {} {
    tclEval {
      # NOTE: extract open checkout directory, where to execute commit
      return [lindex [regexp -line -inline -nocase -- {^check-out:\s+([a-zA-Z]\:\/|\/.*\/)} [eval [getFossilCommand $TCLrepository "$TCLuser" info -v]]] end]

  proc doAddRemove { myCheckOutDir } {
    tclInvoke set myCheckOutDir $myCheckOutDir;
    tclEval {
      # NOTE: must be executed in open checkout directory
      set cdcmd [list cd $myCheckOutDir];
      eval $cdcmd;
      # Addremove in checkout direcotry
      return [eval [getFossilCommand "" "" addremove -n]]

  proc doCommit { myCheckOutDir myCommitMsg } {
    tclInvoke set myCheckOutDir $myCheckOutDir;
    tclInvoke set myCommitMsg $myCommitMsg;
    tclEval {
      # NOTE: must be executed in open checkout directory
      set cdcmd [list cd $myCheckOutDir];
      eval $cdcmd;
      #Commit TODO - How to capture child's execution output?
      set ciasync [eval [getFossilCommand "" "$TCLuser" ci -m $myCommitMsg ] &];
      return $ciasync; # only child's PID 


  set th1CheckoutDir [getCheckoutDir]
  html "Repository is open in:$th1CheckoutDir<br>";

  set MyForm [html "<form method='post' action='$baseurl/$current_page'>
    <input name='commit-form' type='hidden'>
    <textarea name='q' rows='5' cols='80' placeholder='Please, describe your changes here.' autofocus></textarea><br>
    <input name='submit' value='Commit' type='submit'>

  # Process form data
  set th1CommitMsg [getParameter q];
  html "Commit message:<br>$th1CommitMsg<br>"
  if {[string length  $th1CommitMsg] > 0} {
    set MyAddRemove [doAddRemove $th1CheckoutDir];   
    html  "MyAddRemove-output:$MyAddRemove<br>";     
    set MyCommit [doCommit $th1CheckoutDir $th1CommitMsg];
    html  "MyCommit-output:<br>$MyCommit<br>"
  } else {
    html "No commit message."

By anonymous on 2018-09-22 01:12:37 [link]

Have considered using fossil via cgi?

Technically you can make fossil do anything from behind the cgi, you can serve forms and pages, and executing fossil commands on the back-end.