github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/catfile.go (about) 1 package git 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "strconv" 8 "strings" 9 ) 10 11 type CatFileOptions struct { 12 Type, Size, Pretty bool 13 ExitCode bool 14 AllowUnknownType bool 15 16 Batch, BatchCheck bool 17 BatchFmt string 18 FollowSymlinks bool 19 } 20 21 func catFilePretty(c *Client, obj GitObject, opts CatFileOptions) (string, error) { 22 switch t := obj.GetType(); t { 23 case "commit", "tree", "blob", "tag": 24 if opts.Pretty { 25 return obj.String(), nil 26 } 27 return string(obj.GetContent()), nil 28 default: 29 return "", fmt.Errorf("Invalid git type: %s", t) 30 } 31 } 32 func CatFile(c *Client, typ string, s Sha1, opts CatFileOptions) (string, error) { 33 if opts.FollowSymlinks { 34 return "", fmt.Errorf("FollowSymlinks only valid in batch mode") 35 } 36 obj, err := c.GetObject(s) 37 if err != nil { 38 return "", err 39 } 40 41 switch { 42 case opts.ExitCode: 43 // If it was invalid, GetObject would have failed. 44 return "", nil 45 case opts.Pretty: 46 return catFilePretty(c, obj, opts) 47 case opts.Type: 48 return obj.GetType(), nil 49 case opts.Size: 50 return fmt.Sprintf("%v", obj.GetSize()), nil 51 default: 52 switch typ { 53 case "blob": 54 switch o := obj.(type) { 55 case GitBlobObject: 56 return string(obj.GetContent()), nil 57 case GitTagObject: 58 if o.GetHeader("type") != "blob" { 59 return "", fmt.Errorf("tag does not tag a blob") 60 } 61 tagged := o.GetHeader("object") 62 s, err := Sha1FromString(tagged) 63 if err != nil { 64 panic(err) 65 return "", err 66 } 67 68 return CatFile(c, typ, s, opts) 69 } 70 return "", fmt.Errorf("Invalid blob type") 71 case "commit", "tree", "tag": 72 return string(obj.GetContent()), nil 73 default: 74 return "", fmt.Errorf("invalid object type %v", typ) 75 76 } 77 } 78 79 } 80 81 func CatFileBatch(c *Client, opts CatFileOptions, r io.Reader, w io.Writer) error { 82 if opts.Type || opts.Size || opts.ExitCode || opts.Pretty { 83 return fmt.Errorf("May not combine options with --batch") 84 } 85 scanner := bufio.NewScanner(r) 86 scanner.Split(bufio.ScanLines) 87 for scanner.Scan() { 88 line := scanner.Text() 89 var obj []ParsedRevision 90 var err error 91 var rest string 92 var id string 93 if strings.Contains(opts.BatchFmt, "%(rest)") { 94 split := strings.Fields(line) 95 id = split[0] 96 rest = strings.TrimLeft(line[len(split[0]):], "\n \t\r") 97 } else { 98 id = line 99 } 100 if strings.TrimSpace(id) == "" { 101 fmt.Fprintf(w, "%v missing\n", id) 102 continue 103 } 104 obj, _ = RevParse(c, RevParseOptions{Quiet: true}, []string{id}) 105 if len(obj) == 0 { 106 fmt.Fprintf(w, "%v missing\n", id) 107 continue 108 } else if len(obj) > 1 { 109 fmt.Fprintf(w, "%v ambiguous\n", id) 110 continue 111 } 112 gitobj, err := c.GetObject(obj[0].Id) 113 if err != nil { 114 if err.Error() == "Object not found." { 115 fmt.Fprintf(w, "%v missing\n", id) 116 continue 117 } 118 return err 119 } 120 121 if opts.BatchFmt != "" { 122 str := opts.BatchFmt 123 str = strings.Replace(str, "%(objectname)", obj[0].Id.String(), -1) 124 str = strings.Replace(str, "%(objecttype)", gitobj.GetType(), -1) 125 str = strings.Replace(str, "%(objectsize)", strconv.Itoa(gitobj.GetSize()), -1) 126 str = strings.Replace(str, "%(rest)", rest, -1) 127 fmt.Fprintln(w, str) 128 } else { 129 fmt.Fprintf(w, "%v %v %v\n", obj[0].Id, gitobj.GetType(), gitobj.GetSize()) 130 } 131 if opts.Batch && !opts.BatchCheck { 132 fmt.Fprintf(w, "%v\n", string(gitobj.GetContent())) 133 } 134 } 135 if err := scanner.Err(); err != nil { 136 return err 137 } 138 return nil 139 }