-
Notifications
You must be signed in to change notification settings - Fork 6
/
cmd.go
109 lines (99 loc) · 2.52 KB
/
cmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package main
import (
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"
"github.com/charmbracelet/git-lfs-transfer/internal/local"
"github.com/charmbracelet/git-lfs-transfer/transfer"
"github.com/rubyist/tracerx"
)
func ensureDirs(path string) error {
for _, dir := range []string{
"objects", "incomplete", "tmp", "locks",
} {
if err := os.MkdirAll(filepath.Join(path, dir), os.ModePerm); err != nil {
return err
}
}
return nil
}
// Run runs the git-lfs-transfer command against the given I/O and arguments.
func Run(r io.Reader, w io.Writer, args ...string) error {
if len(args) != 2 {
return fmt.Errorf("expected 2 arguments, got %d", len(args))
}
path := args[0]
op := args[1]
_, err := os.Stat(path)
if err != nil {
return err
}
gitdir := path
if !strings.HasSuffix(path, ".git") {
gitdir = filepath.Join(path, ".git")
}
lfsPath := filepath.Join(gitdir, "lfs")
if err := ensureDirs(lfsPath); err != nil {
return err
}
umask := setPermissions(gitdir)
handler := transfer.NewPktline(r, w, logger)
for _, cap := range transfer.Capabilities {
if err := handler.WritePacketText(cap); err != nil {
logger.Log("error sending capability", "cap", cap, "err", err)
}
}
if err := handler.WriteFlush(); err != nil {
logger.Log("error flushing capabilities", "err", err)
}
now := time.Now()
logger.Log("umask", "umask", umask)
backend := local.New(lfsPath, umask, &now)
p := transfer.NewProcessor(handler, backend, logger)
defer logger.Log("done processing commands")
switch op {
case "upload":
return p.ProcessCommands(transfer.UploadOperation)
case "download":
return p.ProcessCommands(transfer.DownloadOperation)
default:
return fmt.Errorf("unknown operation %q", op)
}
}
// Usage returns the command usage.
func Usage() string {
return `Git LFS SSH transfer agent
Usage:
git-lfs-transfer PATH OPERATION
`
}
func init() {
tracerx.DefaultKey = "GIT"
tracerx.Prefix = "trace git-lfs-transfer: "
}
// Command is the main git-lfs-transfer entry.
func Command(stdin io.Reader, stdout io.Writer, stderr io.Writer, args ...string) error {
done := make(chan os.Signal, 1)
errc := make(chan error, 1)
setup(done)
logger.Log("git-lfs-transfer", "version", "v1")
defer logger.Log("git-lfs-transfer completed")
go func() {
errc <- Run(stdin, stdout, args...)
}()
select {
case s := <-done:
logger.Log("signal received", "signal", s)
case err := <-errc:
logger.Log("done running")
fmt.Fprintln(stderr, Usage())
fmt.Fprintln(stderr, err)
if err != nil {
return err
}
}
return nil
}