Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/content-service/pkg/git/porcelain.go
2500 views
1
// Copyright (c) 2020 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package git
6
7
import (
8
"bufio"
9
"io"
10
"strings"
11
12
"golang.org/x/xerrors"
13
)
14
15
const (
16
prefixBranchOID = "# branch.oid "
17
prefixBranchHead = "# branch.head "
18
prefixChangedFile = "1 "
19
prefixRenamedFile = "2 "
20
prefixUnmargedFile = "u "
21
prefixUntrackedFile = "? "
22
)
23
24
// porcelainStatus represents the information gathered from Git porcelain v2 output, see https://git-scm.com/docs/git-status#_porcelain_format_version_2
25
type porcelainStatus struct {
26
BranchOID string
27
BranchHead string
28
UncommitedFiles []string
29
UntrackedFiles []string
30
}
31
32
// ParsePorcelain parses the porcelain v2 format
33
func parsePorcelain(in io.Reader) (*porcelainStatus, error) {
34
res := porcelainStatus{
35
UncommitedFiles: make([]string, 0),
36
UntrackedFiles: make([]string, 0),
37
}
38
39
scanner := bufio.NewScanner(in)
40
for scanner.Scan() {
41
line := scanner.Text()
42
43
if strings.HasPrefix(line, prefixBranchOID) {
44
res.BranchOID = strings.TrimPrefix(line, prefixBranchOID)
45
} else if strings.HasPrefix(line, prefixBranchHead) {
46
res.BranchHead = strings.TrimPrefix(line, prefixBranchHead)
47
} else if strings.HasPrefix(line, prefixChangedFile) ||
48
strings.HasPrefix(line, prefixRenamedFile) ||
49
strings.HasPrefix(line, prefixRenamedFile) ||
50
strings.HasPrefix(line, prefixUnmargedFile) {
51
52
segments := strings.Split(line, " ")
53
file := segments[len(segments)-1]
54
res.UncommitedFiles = append(res.UncommitedFiles, file)
55
} else if strings.HasPrefix(line, prefixUntrackedFile) {
56
segments := strings.Split(line, " ")
57
file := segments[len(segments)-1]
58
res.UntrackedFiles = append(res.UntrackedFiles, file)
59
}
60
}
61
if err := scanner.Err(); err != nil {
62
return nil, xerrors.Errorf("cannot parse porcelain: %v", err)
63
}
64
65
if len(res.UncommitedFiles) == 0 {
66
res.UncommitedFiles = nil
67
}
68
if len(res.UntrackedFiles) == 0 {
69
res.UntrackedFiles = nil
70
}
71
72
return &res, nil
73
}
74
75