Fosi Fossil Service
Small teams. Open source. Built on Fossil.

CaaS / Lamina

Unified Management for Fossil Repositories

Public | Owner: CaaS | Default branch: trunk | Last update: 2026-10-25 00:41

Artifact 2f4b938242597d6316e2422c7220ebab72aa8681a14eed0a4b7d41928d1564a3:


(defmodule lamina_repo_server_tests
  (export all)
  (include-lib "eunit/include/eunit.hrl"))

(defun server-args-put-options-before-repository_test ()
  (lamina_config:put #M(site_url "https://example.test"))
  (let ((args (lamina_repo_server:server-args 'none "demo" "data/repos/demo.fossil" 23456)))
    (let ((repo (lists:last args)))
      (if (and (=:= "server" (hd args))
               (lists:member "--localhost" args)
               (lists:member "--nojail" args)
               (lists:member "--https" args)
               (lists:member "--baseurl" args)
               (lists:member "23456" args)
               (/= 'nomatch (string:find repo "demo.fossil"))
               (not (lists:member "demo.fossil" (lists:droplast args))))
          'ok
          (erlang:error (list "server-args order failed" args))))))

(defun start-error-text-explains-noproc_test ()
  (let ((msg (lamina_repo_ctl:start-error-text
              (tuple 'noproc (tuple 'gen_server 'call (list 'lamina_repo_mgr))))))
    (if (/= 'nomatch (string:find msg "未就绪"))
        'ok
        (erlang:error (list "noproc message failed" msg)))))

(defun start-repo-without-mgr-matches-old-ui-error_test ()
  ;; 旧代码把 gen_server:call 的 EXIT 收成「仓库进程启动失败」。
  (case (whereis 'lamina_repo_mgr)
    ('undefined
     (case (catch (lamina_repo_mgr:start-repo 'none "demo" "/tmp/missing.fossil"))
       (`#(EXIT ,reason)
        (let ((new (lamina_repo_ctl:start-error-text reason)))
          (if (and (/= 'nomatch (string:find (lists:flatten (io_lib:format "~p" (list reason))) "noproc"))
                   (/= 'nomatch (string:find new "未就绪")))
              'ok
              (erlang:error (list "noproc handling changed unexpectedly" reason new)))))
       (other (erlang:error (list "expected EXIT when repo_mgr is missing" other)))))
    (_ 'ok)))

(defun repo-server-listens-after-start-link_test ()
  (require-fossil)
  (process_flag 'trap_exit 'true)
  (let* ((dir (tmpdir))
         (home (filename:join dir "home"))
         (path (filename:join dir "demo.fossil")))
    (filelib:ensure_dir (filename:join home "x"))
    (lamina_config:put (maps:from_list
                          (list (tuple 'site_url "https://hgrc.dev")
                                (tuple 'fossil_home home)
                                (tuple 'repo_dir dir))))
    (case (lamina_fossil_repo:init path "admin")
      (`#(ok ,_)
       (ensure-registry)
       (case (lamina_repo_server:start-link 'none "demo" path)
         (`#(ok ,pid)
          (let ((portnum (lamina_repo_server:get-port "demo")))
            (application:ensure_all_started 'inets)
            (let ((http (httpc:request 'get
                                       (tuple (lists:flatten
                                               (io_lib:format "http://127.0.0.1:~p/" (list portnum)))
                                              '())
                                       (list (tuple 'timeout 3000)
                                             (tuple 'autoredirect 'false))
                                       '())))
              (unlink pid)
              (catch (gen_server:stop pid 'shutdown 3000))
              (cleanup dir)
              (case http
                ((tuple 'ok (tuple (tuple _ status _) _ _))
                 (if (and (is_integer portnum) (>= status 200) (=< status 399))
                     'ok
                     (erlang:error (list "unexpected fossil http status" status portnum))))
                (other (erlang:error (list "fossil http failed" portnum other)))))))
         (other
          (cleanup dir)
          (erlang:error (list "repo_server start-link failed" other)))))
      (other (cleanup dir) (erlang:error (list "fossil init failed" other))))))

(defun create-local-starts-repo-process_test ()
  (require-fossil)
  (process_flag 'trap_exit 'true)
  (let* ((dir (tmpdir))
         (home (filename:join dir "home"))
         (repos (filename:join dir "repos"))
         (db (filename:join dir "platform.db"))
         (key (crypto:hash 'sha256 #"repo-server-test-key")))
    (filelib:ensure_dir (filename:join home "x"))
    (filelib:ensure_dir (filename:join repos "x"))
    (lamina_auth:put-secret-key key)
    (lamina_config:put (maps:from_list
                          (list (tuple 'site_url "https://hgrc.dev")
                                (tuple 'fossil_home home)
                                (tuple 'repo_dir repos)
                                (tuple 'db_path db))))
    (case (lamina_db:open db)
      (`#(ok ,_)
       (ensure-registry)
       (ensure-mgr)
       (let ((result (lamina_repo_ctl:create-local 'none "probe" "probe" "test repo"
                                                     "admin" #"s3cret12")))
         (let ((portnum (lamina_repo_server:get-port "probe"))
               (status (lamina_repo_mgr:status "probe")))
           (catch (lamina_repo_mgr:stop-repo "probe"))
           (unlink-if-pid (whereis 'lamina_repo_mgr))
           (unlink-if-pid (whereis 'lamina_repo_registry))
           (lamina_db:close)
           (cleanup dir)
           (if (and (=:= 'ok result)
                    (is_integer portnum)
                    (is_tuple status)
                    (=:= 'ok (element 1 status)))
               'ok
               (erlang:error (list "create-local did not start repo server"
                                   result portnum status))))))
      (other (cleanup dir) (erlang:error (list "db open failed" other))))))

(defun require-fossil ()
  (let ((bin (lamina_config:fossil-bin)))
    (if (is_atom bin)
        (erlang:error "PATH 中没有 fossil,无法做进程启动实测")
        bin)))

(defun ensure-registry ()
  (case (lamina_repo_registry:start-link)
    (`#(ok ,pid) pid)
    (`#(error #(already_started ,pid)) pid)
    (other (erlang:error (list "registry start failed" other)))))

(defun ensure-mgr ()
  (case (lamina_repo_mgr:start-link)
    (`#(ok ,pid) pid)
    (`#(error #(already_started ,pid)) pid)
    (other (erlang:error (list "repo_mgr start failed" other)))))

(defun tmpdir ()
  (let* ((cwd (element 2 (file:get_cwd)))
         (base (filename:join cwd "_build/tmp"))
         (name (lists:flatten (io_lib:format "repo-server-~p" (list (os:system_time 'microsecond))))))
    (filelib:ensure_dir (filename:join base "x"))
    (let ((dir (filename:join base name)))
      (file:make_dir dir)
      dir)))

(defun unlink-if-pid (pid)
  (if (is_pid pid) (catch (unlink pid)) 'ok))

(defun cleanup (dir)
  (catch (file:del_dir_r dir))
  'ok)

Clone

You can clone this repository with the following command:

fossil clone https://fosi.dev/CaaS/Lamina

Contribute

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