File: command_pointer.go

package info (click to toggle)
git-lfs 3.6.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 4,808 kB
  • sloc: sh: 21,256; makefile: 507; ruby: 417
file content (177 lines) | stat: -rw-r--r-- 4,357 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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
package commands

import (
	"bytes"
	"crypto/sha256"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"os"

	"github.com/git-lfs/git-lfs/v3/git"
	"github.com/git-lfs/git-lfs/v3/lfs"
	"github.com/git-lfs/git-lfs/v3/tr"
	"github.com/spf13/cobra"
)

var (
	pointerFile     string
	pointerCompare  string
	pointerStdin    bool
	pointerCheck    bool
	pointerStrict   bool
	pointerNoStrict bool
)

func pointerCommand(cmd *cobra.Command, args []string) {
	comparing := false
	something := false
	buildOid := ""
	compareOid := ""

	if pointerCheck {
		var r io.ReadCloser
		var err error

		if pointerStrict && pointerNoStrict {
			ExitWithError(errors.New(tr.Tr.Get("Cannot combine --strict with --no-strict")))
		}

		if len(pointerCompare) > 0 {
			ExitWithError(errors.New(tr.Tr.Get("Cannot combine --check with --compare")))
		}

		if len(pointerFile) > 0 {
			if pointerStdin {
				ExitWithError(errors.New(tr.Tr.Get("With --check, --file cannot be combined with --stdin")))
			}
			r, err = os.Open(pointerFile)
			if err != nil {
				ExitWithError(err)
			}
		} else if pointerStdin {
			r = io.NopCloser(os.Stdin)
		} else {
			ExitWithError(errors.New(tr.Tr.Get("Must specify either --file or --stdin with --compare")))
		}

		p, err := lfs.DecodePointer(r)
		if err != nil {
			os.Exit(1)
		}
		if pointerStrict && !p.Canonical {
			os.Exit(2)
		}
		r.Close()
		return
	}

	if len(pointerCompare) > 0 || pointerStdin {
		comparing = true
	}

	if len(pointerFile) > 0 {
		something = true
		buildFile, err := os.Open(pointerFile)
		if err != nil {
			Error(err.Error())
			os.Exit(1)
		}

		oidHash := sha256.New()
		size, err := io.Copy(oidHash, buildFile)
		buildFile.Close()

		if err != nil {
			Error(err.Error())
			os.Exit(1)
		}

		ptr := lfs.NewPointer(hex.EncodeToString(oidHash.Sum(nil)), size, nil)
		fmt.Fprint(os.Stderr, tr.Tr.Get("Git LFS pointer for %s", pointerFile), "\n\n")
		buf := &bytes.Buffer{}
		lfs.EncodePointer(io.MultiWriter(os.Stdout, buf), ptr)

		if comparing {
			buildOid, err = git.HashObject(bytes.NewReader(buf.Bytes()))
			if err != nil {
				Error(err.Error())
				os.Exit(1)
			}
			fmt.Fprint(os.Stderr, "\n", tr.Tr.Get("Git blob OID: %s", buildOid), "\n\n")
		}
	} else {
		comparing = false
	}

	if len(pointerCompare) > 0 || pointerStdin {
		something = true
		compFile, err := pointerReader()
		if err != nil {
			Error(err.Error())
			os.Exit(1)
		}

		buf := &bytes.Buffer{}
		tee := io.TeeReader(compFile, buf)
		_, err = lfs.DecodePointer(tee)
		compFile.Close()

		pointerName := "STDIN"
		if !pointerStdin {
			pointerName = pointerCompare
		}
		fmt.Fprint(os.Stderr, tr.Tr.Get("Pointer from %s", pointerName), "\n\n")

		if err != nil {
			Error(err.Error())
			os.Exit(1)
		}

		fmt.Fprintf(os.Stderr, buf.String())
		if comparing {
			compareOid, err = git.HashObject(bytes.NewReader(buf.Bytes()))
			if err != nil {
				Error(err.Error())
				os.Exit(1)
			}
			fmt.Fprint(os.Stderr, "\n", tr.Tr.Get("Git blob OID: %s", compareOid), "\n")
		}
	}

	if comparing && buildOid != compareOid {
		fmt.Fprint(os.Stderr, "\n", tr.Tr.Get("Pointers do not match"), "\n")
		os.Exit(1)
	}

	if !something {
		Error(tr.Tr.Get("Nothing to do!"))
		os.Exit(1)
	}
}

func pointerReader() (io.ReadCloser, error) {
	if len(pointerCompare) > 0 {
		if pointerStdin {
			return nil, errors.New(tr.Tr.Get("cannot read from STDIN and --pointer"))
		}

		return os.Open(pointerCompare)
	}

	requireStdin(tr.Tr.Get("The --stdin flag expects a pointer file from STDIN."))

	return os.Stdin, nil
}

func init() {
	RegisterCommand("pointer", pointerCommand, func(cmd *cobra.Command) {
		cmd.Flags().StringVarP(&pointerFile, "file", "f", "", "Path to a local file to generate the pointer from.")
		cmd.Flags().StringVarP(&pointerCompare, "pointer", "p", "", "Path to a local file containing a pointer built by another Git LFS implementation.")
		cmd.Flags().BoolVarP(&pointerStdin, "stdin", "", false, "Read a pointer built by another Git LFS implementation through STDIN.")
		cmd.Flags().BoolVarP(&pointerCheck, "check", "", false, "Check whether the given file is a Git LFS pointer.")
		cmd.Flags().BoolVarP(&pointerStrict, "strict", "", false, "Check whether the given Git LFS pointer is canonical.")
		cmd.Flags().BoolVarP(&pointerNoStrict, "no-strict", "", false, "Don't check whether the given Git LFS pointer is canonical.")
	})
}