(defmodule nemoptera_fossil_git
(export all))
(defun export (repo-path git-url git-username git-token)
(let ((url (credential-url git-url git-username git-token))
(mirror (lists:flatten (list repo-path ".git"))))
(filelib:ensure_dir (filename:join mirror "x"))
(nemoptera_fossil:run
(list "git" "export" mirror "--autopush" url "-R" repo-path)
(nemoptera_fossil:clone-timeout-ms))))
(defun credential-url (url username token)
(let ((source (nemoptera_text:to-str url)))
(cond
((lists:prefix "https://" source) (inject source 8 username token))
((lists:prefix "http://" source) (inject source 7 username token))
('true source))))
(defun inject (source scheme-len username token)
(let ((scheme (lists:sublist source scheme-len))
(rest (lists:nthtail scheme-len source)))
(case (string:split rest "/" 'leading)
(`(,authority ,path)
(if (lists:member 64 authority)
source
(lists:flatten
(list scheme (url-encode username) ":" (url-encode token) "@" authority "/" path))))
(_ source))))
(defun url-encode (value)
(url-encode (nemoptera_text:to-str value) '()))
(defun url-encode
(('() acc) (lists:flatten (lists:reverse acc)))
(((cons char rest) acc)
(if (url-safe? char)
(url-encode rest (cons (list char) acc))
(url-encode rest (cons (percent char) acc)))))
(defun url-safe? (char)
(or (and (>= char 48) (=< char 57))
(and (>= char 65) (=< char 90))
(and (>= char 97) (=< char 122))
(lists:member char '(45 46 95 126))))
(defun percent (char)
(let ((hex "0123456789ABCDEF"))
(list 37
(lists:nth (+ 1 (div char 16)) hex)
(lists:nth (+ 1 (rem char 16)) hex))))