github.com/driusan/dgit@v0.0.0-20221118233547-f39f0c15edbb/git/difftree.go (about)

     1  package git
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  	"sort"
     7  )
     8  
     9  // Describes the options that may be specified on the command line for
    10  // "git diff-index". Note that only raw mode is currently supported, even
    11  // though all the other options are parsed/set in this struct.
    12  type DiffTreeOptions struct {
    13  	Patch bool
    14  
    15  	// The 0 value implies 3.
    16  	NumContextLines int
    17  
    18  	Raw bool
    19  
    20  	// Unimplemented. Probably never will be.
    21  	CompactionHeuristic bool
    22  
    23  	// Can be "default", "myers", "minimal", "patience", or "histogram"
    24  	DiffAlgorithm string
    25  
    26  	StatWidth, StatNameWidth, StatCount int
    27  	NumStat                             bool
    28  	ShortStat                           bool
    29  
    30  	DirStat string
    31  
    32  	Summary bool
    33  
    34  	NullTerminate bool
    35  
    36  	NameOnly, NameStatus bool
    37  
    38  	Submodule string
    39  
    40  	// Colour can have three states: "always" (true), "never" (false), or "auto" (nil)
    41  	Color *bool
    42  
    43  	// "color", "plain", "porcelain", or "none"
    44  	WordDiff string
    45  
    46  	WordDiffRegex *regexp.Regexp
    47  
    48  	NoRenames bool
    49  
    50  	// Warn if changes introduce conflict markers or whitespace errors.
    51  	Check bool
    52  
    53  	// Valid options in the []string are "old", "new", or "context"
    54  	WhitespaceErrorHighlight []string
    55  
    56  	FullIndex, Binary bool
    57  
    58  	// Number of characters to abbreviate the hexadecimal object name to.
    59  	Abbrev int
    60  
    61  	// Recurse into subtrees.
    62  	Recurse bool
    63  
    64  	// Diff the initial commit against the empty tree
    65  	Root bool
    66  
    67  	// And 6 million more options, which are mostly for the unsupported patch
    68  	// format anyways.
    69  }
    70  
    71  func DiffTree(c *Client, opt *DiffTreeOptions, tree1, tree2 Treeish, paths []string) ([]HashDiff, error) {
    72  	t1, err := tree1.TreeID(c)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  
    77  	var t2 TreeID
    78  	if tree2 != nil {
    79  		t, err := tree2.TreeID(c)
    80  		if err != nil {
    81  			return nil, err
    82  		}
    83  		t2 = t
    84  	} else {
    85  		// No tree, use tree 1's parent
    86  		if c1, ok := tree1.(Commitish); ok {
    87  			c1a, err := c1.CommitID(c)
    88  			if err != nil {
    89  				return nil, err
    90  			}
    91  			parents, err := c1a.Parents(c)
    92  			if err != nil {
    93  				return nil, err
    94  			}
    95  			if len(parents) > 1 {
    96  				return nil, fmt.Errorf("Parent is a merge commit")
    97  			} else if len(parents) == 0 {
    98  				if !opt.Root {
    99  					return nil, nil
   100  				}
   101  				t2 = TreeID{}
   102  			} else {
   103  				ptree, err := parents[0].TreeID(c)
   104  				if err != nil {
   105  					return nil, err
   106  				}
   107  				t2 = ptree
   108  			}
   109  
   110  		} else {
   111  			return nil, fmt.Errorf("Can not determine parent of tree")
   112  		}
   113  	}
   114  
   115  	tree1Objects, err := t1.GetAllObjects(c, "", opt.Recurse, opt.Recurse)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	if opt.Root && t2 == (TreeID{}) {
   120  		// There is no parent to check against and we --root was
   121  		// passed, so just include everything from tree1
   122  		var val []HashDiff = make([]HashDiff, 0, len(tree1Objects))
   123  		for name, sha := range tree1Objects {
   124  			val = append(val, HashDiff{name, TreeEntry{}, sha, 0, 0})
   125  		}
   126  		sort.Sort(ByName(val))
   127  
   128  		return val, nil
   129  	}
   130  	tree2Objects, err := t2.GetAllObjects(c, "", opt.Recurse, opt.Recurse)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	var val []HashDiff
   136  
   137  	for name, sha := range tree1Objects {
   138  		if osha := tree2Objects[name]; sha != osha {
   139  			val = append(val, HashDiff{name, sha, osha, 0, 0})
   140  		}
   141  	}
   142  
   143  	// Check for files that were added in tree2 but missing in tree1, which
   144  	// would have gotten caught by the above ranging.
   145  	for name, sha := range tree2Objects {
   146  		if _, ok := tree1Objects[name]; !ok {
   147  			val = append(val, HashDiff{name, TreeEntry{Sha1{}, 0}, sha, 0, 0})
   148  		}
   149  	}
   150  
   151  	sort.Sort(ByName(val))
   152  
   153  	return val, nil
   154  }