Skip to content
  • Junio C Hamano's avatar
    attribute macro support · f48fd688
    Junio C Hamano authored
    
    
    This adds "attribute macros" (for lack of better name).  So far,
    we have low-level attributes such as crlf and diff, which are
    defined in operational terms --- setting or unsetting them on a
    particular path directly affects what is done to the path.  For
    example, in order to decline diffs or crlf conversions on a
    binary blob, no diffs on PostScript files, and treat all other
    files normally, you would have something like these:
    
    	*		diff crlf
    	*.ps		!diff
    	proprietary.o	!diff !crlf
    
    That is fine as the operation goes, but gets unwieldy rather
    rapidly, when we start adding more low-level attributes that are
    defined in operational terms.  A near-term example of such an
    attribute would be 'merge-3way' which would control if git
    should attempt the usual 3-way file-level merge internally, or
    leave merging to a specialized external program of user's
    choice.  When it is added, we do _not_ want to force the users
    to update the above to:
    
    	*		diff crlf merge-3way
    	*.ps		!diff
    	proprietary.o	!diff !crlf !merge-3way
    
    The way this patch solves this issue is to realize that the
    attributes the user is assigning to paths are not defined in
    terms of operations but in terms of what they are.
    
    All of the three low-level attributes usually make sense for
    most of the files that sane SCM users have git operate on (these
    files are typically called "text').  Only a few cases, such as
    binary blob, need exception to decline the "usual treatment
    given to text files" -- and people mark them as "binary".
    
    So this allows the $GIT_DIR/info/alternates and .gitattributes
    at the toplevel of the project to also specify attributes that
    assigns other attributes.  The syntax is '[attr]' followed by an
    attribute name followed by a list of attribute names:
    
    	[attr] binary	!diff !crlf !merge-3way
    
    When "binary" attribute is set to a path, if the path has not
    got diff/crlf/merge-3way attribute set or unset by other rules,
    this rule unsets the three low-level attributes.
    
    It is expected that the user level .gitattributes will be
    expressed mostly in terms of attributes based on what the files
    are, and the above sample would become like this:
    
    	(built-in attribute configuration)
    	[attr] binary	!diff !crlf !merge-3way
    	*		diff crlf merge-3way
    
    	(project specific .gitattributes)
    	proprietary.o	binary
    
    	(user preference $GIT_DIR/info/attributes)
    	*.ps		!diff
    
    There are a few caveats.
    
     * As described above, you can define these macros only in
       $GIT_DIR/info/attributes and toplevel .gitattributes.
    
     * There is no attempt to detect circular definition of macro
       attributes, and definitions are evaluated from bottom to top
       as usual to fill in other attributes that have not yet got
       values.  The following would work as expected:
    
    	[attr] text	diff crlf
    	[attr] ps	text !diff
    	*.ps	ps
    
       while this would most likely not (I haven't tried):
    
    	[attr] ps	text !diff
    	[attr] text	diff crlf
    	*.ps	ps
    
     * When a macro says "[attr] A B !C", saying that a path does
       not have attribute A does not let you tell anything about
       attributes B or C.  That is, given this:
    
    	[attr] text	diff crlf
    	[attr] ps	text !diff
    	*.txt !ps
    
      path hello.txt, which would match "*.txt" pattern, would have
      "ps" attribute set to zero, but that does not make text
      attribute of hello.txt set to false (nor diff attribute set to
      true).
    
    Signed-off-by: default avatarJunio C Hamano <junkio@cox.net>
    f48fd688