File: cmd.go

package info (click to toggle)
gitlab-shell 14.35.0%2Bds1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 23,652 kB
  • sloc: ruby: 1,129; makefile: 583; sql: 391; sh: 384
file content (109 lines) | stat: -rw-r--r-- 2,579 bytes parent folder | download
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
}