HGRC Quarry Fossil Service
Simple tools for lasting software

Infrastructure as a Service / Nemoptera

A solid foundation to fork, tweak, and enhance.

Public | Owner: Infrastructure as a Service | Default branch: trunk | Last update: 2026-11-08 16:13

Artifact c6a6330de851f7b0e79678cef0c7ac60ea598db4fdd6cf0561dd9137d25e3b98:


(defmodule nemoptera_fossil
  (export all))

(defun default-timeout-ms () 120000)
(defun clone-timeout-ms () 300000)

(defun run (args)
  (run args (default-timeout-ms)))

(defun run (args timeout-ms)
  (let ((bin (nemoptera_config:fossil-bin)))
    (if (is_list bin)
        (run-bin bin args timeout-ms)
        `#(error #(enoent "fossil executable was not found")))))

(defun run-bin (bin args timeout-ms)
  (let ((cmd-args (lists:map #'to-charlist/1 args))
        (home (to-charlist (filename:absname (nemoptera_config:get 'fossil_home "data/fossil-home")))))
    (filelib:ensure_dir (filename:join (binary_to_list (list_to_binary home)) "x"))
    (case (catch
           (open_port (tuple 'spawn_executable (to-charlist bin))
                      (list 'stream 'in 'binary 'exit_status 'hide 'stderr_to_stdout
                            (tuple 'env (list (tuple "FOSSIL_HOME" home)
                                              (tuple "HOME" home)
                                              (tuple "USER" (os:getenv "USER" "nemoptera"))))
                            (tuple 'args cmd-args))))
      (`#(EXIT ,reason) (open-error reason))
      (port (collect port #"" timeout-ms)))))

(defun collect (port acc timeout-ms)
  (receive
    (`#(,port #(data ,data))
     (collect port (iolist_to_binary (list acc data)) timeout-ms))
    (`#(,port #(exit_status 0))
     `#(ok ,(binary_to_list acc)))
    (`#(,port #(exit_status ,code))
     `#(error #(exit_status ,code ,(binary_to_list acc))))
    (after timeout-ms
      (catch (port_close port))
      `#(error timeout))))

(defun open-error (reason)
  (let ((text (lists:flatten (io_lib:format "~p" (list reason)))))
    (cond
      ((or (=:= reason 'enoent) (lists:member "enoent" (string:lexemes text "{} ,")))
       `#(error #(enoent ,text)))
      ((or (=:= reason 'eacces) (lists:member "eacces" (string:lexemes text "{} ,")))
       `#(error #(eacces ,text)))
      ('true `#(error #(enoent ,text))))))

(defun error-message (reason)
  (case reason
    (`#(enoent ,_) "fossil executable or target path was not found")
    (`#(eacces ,_) "fossil could not access the target path")
    (`#(exit_status ,code ,out)
     (lists:flatten (io_lib:format "fossil exited ~p: ~s" (list code (nemoptera_text:clip out 500)))))
    ('timeout "fossil command timed out")
    (`#(timeout ,out)
     (lists:flatten (io_lib:format "fossil server did not start: ~s" (list (nemoptera_text:clip out 300)))))
    (_ (lists:flatten (io_lib:format "fossil command failed: ~p" (list reason))))))

(defun to-charlist (value)
  (cond
    ((is_binary value) (binary_to_list value))
    ((is_list value) value)
    ('true (lists:flatten (io_lib:format "~p" (list value))))))

Clone

You can clone this repository with the following command:

fossil clone https://hgrc.dev/IaaS/Nemoptera Nemoptera.fossil

Contribute

The best way to contribute is through e-mail. See the project documentation for more details.