login

<     >

2023-08-16 00:07:13 (UTC-03:00)

Marcel Rodrigues <marcelgmr@gmail.com>

add tar.gz archive downloads

diff --git a/cogit/cogit.lua b/cogit/cogit.lua
index 1fc3da7..56a1afd 100644
--- a/cogit/cogit.lua
+++ b/cogit/cogit.lua
@@ -104,6 +104,26 @@ function Cogit:is_admin(cookies)
     return self.sessions[session_id]
 end
 
+function Cogit:archive(rname, rev, fmt)
+    local arc_path = "/tmp/cogit-archive/"
+    os.execute("mkdir -p "..arc_path)
+    local aname = rname.."-"..rev
+    local fname = aname.."."..fmt
+    -- check if file already exists
+    local fp = io.open(arc_path..fname)
+    if fp == nil then
+        local cmd = "GIT_DIR='"..self.path.."/"..rname..".git' "
+        cmd = cmd.."git archive --prefix="..aname.."/"
+        cmd = cmd.." -o "..arc_path..fname.." "..rev
+        os.execute(cmd)
+        self:log(LOG_INFO, "generated archive "..fname)
+    else
+        self:log(LOG_INFO, "using cached archive "..fname)
+        fp:close()
+    end
+    return arc_path, fname
+end
+
 function Cogit:routes()
     return {
     {"GET", "/?",
@@ -170,7 +190,7 @@ function Cogit:routes()
         local tnames = repo:tags()
         local env = {
             title=self.title, is_admin=is_admin, repo=repo,
-            rname=rname, bnames=bnames, tnames=tnames,
+            rname=rname, bnames=bnames, tnames=tnames, fmt=self.archive_fmt,
         }
         return {fname="view/repo.html", env=env}
     end},
@@ -219,6 +239,27 @@ function Cogit:routes()
         }
         return {fname="view/commit.html", env=env}
     end},
+    {"GET", "/repo/([%w_-]+)/archive/(%S+)",
+    function (req, rname, cid)
+        local repo = self.repos[rname]
+        if repo == nil then
+            return "Page not found", 404, "Not found"
+        end
+        local is_admin = self:is_admin(req.cookies)
+        if not is_admin and is_private(self.descs[rname]) then
+            return "/login", 303
+        end
+        local commit = repo:commit(cid)
+        if commit == nil then
+            return "Page not found", 404, "Not found"
+        end
+        local path, fname = self:archive(rname, cid, self.archive_fmt)
+        local headers = {
+            ["Content-Type"] = 'application/gzip',
+            ["Content-Disposition"] = 'attachment; filename="'..fname..'"',
+        }
+        return {fname=path..fname, headers=headers}
+    end},
     {"GET", "/repo/([%w_-]+)/commit/([%w_-]+)/tree/(.*)",
     function (req, rname, cid, path)
         local repo = self.repos[rname]
@@ -247,7 +288,7 @@ function Cogit:routes()
         end
         local env = {
             title=self.title, is_admin=is_admin, rname=rname, cid=cid,
-            path=path, base=base, parts=parts, node=node,
+            path=path, base=base, parts=parts, node=node, fmt=self.archive_fmt,
         }
         if node.type_ == "dir" then
             return {fname="view/dir.html", env=env}
@@ -267,6 +308,7 @@ local function new_cogit(path, port, title, log_level)
         limit=20,
         session_age=3*24*60*60,
         sessions={},
+        archive_fmt="tar.gz",
         initialized=false,
     }
     self = setmetatable(self, Cogit)

diff --git a/view/dir.html b/view/dir.html
index 33859c9..7256e56 100644
--- a/view/dir.html
+++ b/view/dir.html
@@ -16,8 +16,15 @@
     &gt;
     <a href="/repo/{{$rname}}/commit/{{$cid}}">{{$cid}}</a>
     &gt;
+    % if #$parts == 0 then
+    % set archive_name = $rname.."-"..$cid.."."..$fmt
+    <a href="/repo/{{$rname}}/archive/{{$cid}}" download="{{$archive_name}}">
+      {{$archive_name}}
+    </a>
+    % else
     % set partial = "/repo/"..$rname.."/commit/"..$cid.."/tree"
     <a href="{{$partial}}/">tree</a>
+    % end
     % for part in $parts do
     % set partial = $partial .. "/" .. $part
     &gt;

diff --git a/view/repo.html b/view/repo.html
index 120d9a2..0fd82e9 100644
--- a/view/repo.html
+++ b/view/repo.html
@@ -6,6 +6,7 @@
   <style>
     #nav-bar { float: left; }
     % include view/auth.css
+    % include view/table.css
   </style>
 </head>
 <body>
@@ -16,20 +17,44 @@
   </div>
   % include view/auth.html
   <br>
-  <p>Branches:</p>
-  <ul>
+  <h3 class="center">Branches</h3>
+  <table class="center">
+    <tr>
+      <th>history</th>
+      <th>archive</th>
+    </tr>
     % for bname in $bnames do
-    <li><a href="/repo/{{$rname}}/history/{{$bname}}">{{$bname}}</a></li>
+    <tr>
+      <td><a href="/repo/{{$rname}}/history/{{$bname}}">{{$bname}}</a></td>
+      % set archive_name = $rname.."-"..$bname.."."..$fmt
+      <td>
+        <a href="/repo/{{$rname}}/archive/{{$bname}}" download="{{$archive_name}}">
+          {{$archive_name}}
+        </a>
+      </td>
+    </tr>
     % end
-  </ul>
+  </table>
   % if #$tnames > 0 then
-  <p>Tags:</p>
-  <ul>
+  <h3 class="center">Tags</h3>
+  <table class="center">
+    <tr>
+      <th>commit</th>
+      <th>archive</th>
+    </tr>
     % for tname in $tnames do
       % set cid = $repo:commit($tname.."^{}"):id()
-    <li><a href="/repo/{{$rname}}/commit/{{$cid}}">{{$tname}}</a></li>
+    <tr>
+      <td><a href="/repo/{{$rname}}/commit/{{$cid}}">{{$tname}}</a></td>
+      % set archive_name = $rname.."-"..$tname.."."..$fmt
+      <td>
+        <a href="/repo/{{$rname}}/archive/{{$tname}}" download="{{$archive_name}}">
+          {{$archive_name}}
+        </a>
+      </td>
+    </tr>
     % end
-  </ul>
+  </table>
   % end
 </body>
 </html>