+2
-2
appview/pages/templates/repo/index.html
+2
-2
appview/pages/templates/repo/index.html
+2
-2
appview/pages/templates/repo/tree.html
+2
-2
appview/pages/templates/repo/tree.html
···
44
<i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }}
45
</div>
46
</a>
47
-
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time>
48
</div>
49
</div>
50
{{ end }}
···
59
<i class="w-3 h-3" data-lucide="file"></i>{{ .Name }}
60
</div>
61
</a>
62
-
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.Author.When }}</time>
63
</div>
64
</div>
65
{{ end }}
···
44
<i class="w-3 h-3 fill-current" data-lucide="folder"></i>{{ .Name }}
45
</div>
46
</a>
47
+
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time>
48
</div>
49
</div>
50
{{ end }}
···
59
<i class="w-3 h-3" data-lucide="file"></i>{{ .Name }}
60
</div>
61
</a>
62
+
<time class="text-xs text-gray-500">{{ timeFmt .LastCommit.When }}</time>
63
</div>
64
</div>
65
{{ end }}
+26
-11
knotserver/git/git.go
+26
-11
knotserver/git/git.go
···
9
"os/exec"
10
"path"
11
"sort"
12
"strings"
13
"sync"
14
"time"
···
17
"github.com/go-git/go-git/v5"
18
"github.com/go-git/go-git/v5/plumbing"
19
"github.com/go-git/go-git/v5/plumbing/object"
20
)
21
22
var (
···
297
return nil
298
}
299
300
-
func (g *GitRepo) LastCommitForPath(path string) (*object.Commit, error) {
301
cacheKey := fmt.Sprintf("%s:%s", g.h.String(), path)
302
cacheMu.RLock()
303
-
if commit, found := commitCache.Get(cacheKey); found {
304
cacheMu.RUnlock()
305
-
return commit.(*object.Commit), nil
306
}
307
cacheMu.RUnlock()
308
309
-
cmd := exec.Command("git", "-C", g.path, "log", "-1", "--format=%H", "--", path)
310
311
var out bytes.Buffer
312
cmd.Stdout = &out
···
316
return nil, fmt.Errorf("failed to get commit hash: %w", err)
317
}
318
319
-
commitHash := strings.TrimSpace(out.String())
320
-
if commitHash == "" {
321
return nil, fmt.Errorf("no commits found for path: %s", path)
322
}
323
324
hash := plumbing.NewHash(commitHash)
325
326
-
commit, err := g.r.CommitObject(hash)
327
-
if err != nil {
328
-
return nil, err
329
}
330
331
cacheMu.Lock()
332
-
commitCache.Set(cacheKey, commit, 1)
333
cacheMu.Unlock()
334
335
-
return commit, nil
336
}
337
338
func newInfoWrapper(
···
9
"os/exec"
10
"path"
11
"sort"
12
+
"strconv"
13
"strings"
14
"sync"
15
"time"
···
18
"github.com/go-git/go-git/v5"
19
"github.com/go-git/go-git/v5/plumbing"
20
"github.com/go-git/go-git/v5/plumbing/object"
21
+
"github.com/sotangled/tangled/types"
22
)
23
24
var (
···
299
return nil
300
}
301
302
+
func (g *GitRepo) LastCommitForPath(path string) (*types.LastCommitInfo, error) {
303
cacheKey := fmt.Sprintf("%s:%s", g.h.String(), path)
304
cacheMu.RLock()
305
+
if commitInfo, found := commitCache.Get(cacheKey); found {
306
cacheMu.RUnlock()
307
+
return commitInfo.(*types.LastCommitInfo), nil
308
}
309
cacheMu.RUnlock()
310
311
+
cmd := exec.Command("git", "-C", g.path, "log", "-1", "--format=%H %ct", "--", path)
312
313
var out bytes.Buffer
314
cmd.Stdout = &out
···
318
return nil, fmt.Errorf("failed to get commit hash: %w", err)
319
}
320
321
+
output := strings.TrimSpace(out.String())
322
+
if output == "" {
323
return nil, fmt.Errorf("no commits found for path: %s", path)
324
}
325
326
+
parts := strings.SplitN(output, " ", 2)
327
+
if len(parts) < 2 {
328
+
return nil, fmt.Errorf("unexpected commit log format")
329
+
}
330
+
331
+
commitHash := parts[0]
332
+
commitTimeUnix, err := strconv.ParseInt(parts[1], 10, 64)
333
+
if err != nil {
334
+
return nil, fmt.Errorf("parsing commit time: %w", err)
335
+
}
336
+
commitTime := time.Unix(commitTimeUnix, 0)
337
+
338
hash := plumbing.NewHash(commitHash)
339
340
+
commitInfo := &types.LastCommitInfo{
341
+
Hash: hash,
342
+
Message: "",
343
+
When: commitTime,
344
}
345
346
cacheMu.Lock()
347
+
commitCache.Set(cacheKey, commitInfo, 1)
348
cacheMu.Unlock()
349
350
+
return commitInfo, nil
351
}
352
353
func newInfoWrapper(
+10
-2
types/tree.go
+10
-2
types/tree.go
···
1
package types
2
3
import (
4
+
"time"
5
+
6
+
"github.com/go-git/go-git/v5/plumbing"
7
)
8
9
// A nicer git tree representation.
···
14
IsFile bool `json:"is_file"`
15
IsSubtree bool `json:"is_subtree"`
16
17
+
LastCommit *LastCommitInfo `json:"last_commit,omitempty"`
18
+
}
19
+
20
+
type LastCommitInfo struct {
21
+
Hash plumbing.Hash
22
+
Message string
23
+
When time.Time
24
}