fork of https://github.com/sourcegraph/zoekt
1// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package gitindex
16
17import (
18 "bytes"
19 "fmt"
20
21 "github.com/go-git/go-git/v5/plumbing/format/config"
22)
23
24// SubmoduleEntry represent one entry in a .gitmodules file
25type SubmoduleEntry struct {
26 Path string
27 URL string
28 Branch string
29}
30
31// ParseGitModules parses the contents of a .gitmodules file.
32func ParseGitModules(content []byte) (map[string]*SubmoduleEntry, error) {
33 buf := bytes.NewBuffer(content)
34
35 // Handle the possibility that .gitmodules has a UTF-8 BOM, which would
36 // otherwise break the scanner.
37 // https://stackoverflow.com/a/21375405
38 skipIfPrefix(buf, []byte("\uFEFF"))
39
40 dec := config.NewDecoder(buf)
41 cfg := &config.Config{}
42
43 if err := dec.Decode(cfg); err != nil {
44 return nil, fmt.Errorf("error decoding content %s: %w", string(content), err)
45 }
46
47 result := map[string]*SubmoduleEntry{}
48 for _, s := range cfg.Sections {
49 if s.Name != "submodule" {
50 continue
51 }
52
53 for _, ss := range s.Subsections {
54 name := ss.Name
55 e := &SubmoduleEntry{}
56 for _, o := range ss.Options {
57 switch o.Key {
58 case "branch":
59 e.Branch = o.Value
60 case "path":
61 e.Path = o.Value
62 case "url":
63 e.URL = o.Value
64 }
65 }
66
67 result[name] = e
68 }
69 }
70
71 return result, nil
72}
73
74// skipIfPrefix will detect if the unread portion of buf starts with
75// prefix. If it does, it will read over those bytes.
76func skipIfPrefix(buf *bytes.Buffer, prefix []byte) {
77 if bytes.HasPrefix(buf.Bytes(), prefix) {
78 buf.Next(len(prefix))
79 }
80}