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  }