summaryrefslogtreecommitdiff
path: root/attr.c
AgeCommit message (Collapse)AuthorFilesLines
2012-09-13attr: failure to open a .gitattributes file is OK with ENOTDIRLibravatar Junio C Hamano1-1/+1
Often we consult an in-tree .gitattributes file that exists per directory. Majority of directories do not usually have such a file, and it is perfectly fine if we cannot open it because there is no such file, but we do want to know when there is an I/O or permission error. Earlier, we made the codepath warn when we fail to open it for reasons other than ENOENT for that reason. We however sometimes have to attempt to open the .gitattributes file from a directory that does not exist in the commit that is currently checked out. "git pack-objects" wants to know if a path is marked with "-delta" attributes, and "git archive" wants to know about export-ignore and export-subst attributes. Both commands may and do need to ask the attributes system about paths in an arbitrary commit. "git diff", after removing an entire directory, may want to know textconv on paths that used to be in that directory. Make sure we also ignore a failure to open per-directory attributes file due to ENOTDIR. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-08-21warn_on_inaccessible(): a helper to warn on inaccessible pathsLibravatar Junio C Hamano1-1/+1
The previous series introduced warnings to multiple places, but it could become tiring to see the warning on the same path over and over again during a single run of Git. Making just one function responsible for issuing this warning, we could later choose to keep track of which paths we issued a warning (it would involve a hash table of paths after running them through real_path() or something) in order to reduce noise. Right now we do not know if the noise reduction is necessary, but it still would be a good code reduction/sharing anyway. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-08-21attr: warn on inaccessible attribute filesLibravatar Jeff King1-1/+4
Just like config and gitignore files, we silently ignore missing or inaccessible attribute files. An existent but inaccessible file is probably a configuration error, so let's warn the user. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-07-24attr: make sure we have an xdg path before using itLibravatar Jeff King1-5/+7
If we don't have a core.attributesfile configured, we fall back to checking XDG config, which is usually $HOME/.config/git/attributes. However, if $HOME is unset, then home_config_paths will return NULL, and we end up calling fopen(NULL). Depending on your system, this may or may not cause the accompanying test to fail (e.g., on Linux and glibc, the address will go straight to open, which will return EFAULT). However, valgrind will reliably notice the error. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-06-25Let core.attributesfile default to $XDG_CONFIG_HOME/git/attributesLibravatar Huynh Khoi Nguyen Nguyen1-7/+10
This gives the default value for the core.attributesfile variable following the exact same logic of the previous change for the core.excludesfile setting. Signed-off-by: Huynh Khoi Nguyen Nguyen <Huynh-Khoi-Nguyen.Nguyen@ensimag.imag.fr> Signed-off-by: Valentin Duperray <Valentin.Duperray@ensimag.imag.fr> Signed-off-by: Franck Jonas <Franck.Jonas@ensimag.imag.fr> Signed-off-by: Lucien Kong <Lucien.Kong@ensimag.imag.fr> Signed-off-by: Thomas Nguy <Thomas.Nguy@ensimag.imag.fr> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-11Merge branch 'maint-1.7.6' into maint-1.7.7Libravatar Junio C Hamano1-0/+1
* maint-1.7.6: attr: fix leak in free_attr_elem t2203: fix wrong commit command
2012-01-11attr: fix leak in free_attr_elemLibravatar Jeff King1-0/+1
This function frees the individual "struct match_attr"s we have allocated, but forgot to free the array holding their pointers, leading to a minor memory leak (but it can add up after checking attributes for paths in many directories). Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-10Merge the attributes fix in from maint-1.6.6 branchLibravatar Junio C Hamano1-32/+43
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-10attr.c: clarify the logic to pop attr_stackLibravatar Junio C Hamano1-1/+10
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-10attr.c: make bootstrap_attr_stack() leave earlyLibravatar Junio C Hamano1-30/+31
Thas would de-dent the body of a function that has grown rather large over time, making it a bit easier to read. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-10attr: drop misguided defensive codingLibravatar Jeff King1-1/+1
In prepare_attr_stack, we pop the old elements of the stack (which were left from a previous lookup and may or may not be useful to us). Our loop to do so checks that we never reach the top of the stack. However, the code immediately afterwards will segfault if we did actually reach the top of the stack. Fortunately, this is not an actual bug, since we will never pop all of the stack elements (we will always keep the root gitattributes, as well as the builtin ones). So the extra check in the loop condition simply clutters the code and makes the intent less clear. Let's get rid of it. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2012-01-10attr: don't confuse prefixes with leading directoriesLibravatar Jeff King1-1/+2
When we prepare the attribute stack for a lookup on a path, we start with the cached stack from the previous lookup (because it is common to do several lookups in the same directory hierarchy). So the first thing we must do in preparing the stack is to pop any entries that point to directories we are no longer interested in. For example, if our stack contains gitattributes for: foo/bar/baz foo/bar foo but we want to do a lookup in "foo/bar/bleep", then we want to pop the top element, but retain the others. To do this we walk down the stack from the top, popping elements that do not match our lookup directory. However, the test do this simply checked strncmp, meaning we would mistake "foo/bar/baz" as a leading directory of "foo/bar/baz_plus". We must also check that the character after our match is '/', meaning we matched the whole path component. There are two special cases to consider: 1. The top of our attr stack has the empty path. So we must not check for '/', but rather special-case the empty path, which always matches. 2. Typically when matching paths in this way, you would also need to check for a full string match (i.e., the character after is '\0'). We don't need to do so in this case, though, because our path string is actually just the directory component of the path to a file (i.e., we know that it terminates with "/", because the filename comes after that). Helped-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-11attr.c: respect core.ignorecase when matching attribute patternsLibravatar Brandon Casey1-2/+3
When core.ignorecase is true, the file globs configured in the .gitattributes file should be matched case-insensitively against the paths in the working directory. Let's do so. Plus, add some tests. The last set of tests is performed only on a case-insensitive filesystem. Those tests make sure that git handles the case where the .gitignore file resides in a subdirectory and the user supplies a path that does not match the case in the filesystem. In that case^H^H^H^Hsituation, part of the path supplied by the user is effectively interpreted case-insensitively, and part of it is dependent on the setting of core.ignorecase. git will currently only match the portion of the path below the directory holding the .gitignore file according to the setting of core.ignorecase. This is also partly future-proofing. Currently, git builds the attr stack based on the path supplied by the user, so we don't have to do anything special (like use strcmp_icase) to handle the parts of that path that don't match the filesystem with respect to case. If git instead built the attr stack by scanning the repository, then the paths in the origin field would not necessarily match the paths supplied by the user. If someone makes a change like that in the future, these tests will notice. Signed-off-by: Brandon Casey <drafnel@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-06attr: read core.attributesfile from git_default_core_configLibravatar Junio C Hamano1-13/+2
This code calls git_config from a helper function to parse the config entry it is interested in. Calling git_config in this way may cause a problem if the helper function can be called after a previous call to git_config by another function since the second call to git_config may reset some variable to the value in the config file which was previously overridden. The above is not a problem in this case since the function passed to git_config only parses one config entry and the variable it sets is not assigned outside of the parsing function. But a programmer who desires all of the standard config options to be parsed may be tempted to modify git_attr_config() so that it falls back to git_default_config() and then it _would_ be vulnerable to the above described behavior. So, move the call to git_config up into the top-level cmd_* function and move the responsibility for parsing core.attributesfile into the main config file parser. Which is only the logical thing to do ;-) Signed-off-by: Brandon Casey <drafnel@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-06cleanup: use internal memory allocation wrapper functions everywhereLibravatar Brandon Casey1-1/+1
The "x"-prefixed versions of strdup, malloc, etc. will check whether the allocation was successful and terminate the process otherwise. A few uses of malloc were left alone since they already implemented a graceful path of failure or were in a quasi external library like xdiff. Additionally, the call to malloc in compat/win32/syslog.c was not modified since the syslog() implemented there is a die handler and a call to the x-wrappers within a die handler could result in recursion should memory allocation fail. This will have to be addressed separately. Signed-off-by: Brandon Casey <drafnel@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-10-06attr.c: avoid inappropriate access to strbuf "buf" memberLibravatar Brandon Casey1-13/+11
This code sequence performs a strcpy into the buf member of a strbuf struct. The strcpy may move the position of the terminating nul of the string and effectively change the length of string so that it does not match the len member of the strbuf struct. Currently, this sequence works since the strbuf was given a hint when it was initialized to allocate enough space to accomodate the string that will be strcpy'ed, but this is an implementation detail of strbufs, not a guarantee. So, lets rework this sequence so that the strbuf is only manipulated by strbuf functions, and direct modification of its "buf" member is not necessary. Signed-off-by: Brandon Casey <drafnel@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-28Merge branch 'mh/attr'Libravatar Junio C Hamano1-50/+63
* mh/attr: Unroll the loop over passes Change while loop into for loop Determine the start of the states outside of the pass loop Change parse_attr() to take a pointer to struct attr_state Increment num_attr in parse_attr_line(), not parse_attr() Document struct match_attr Add a file comment
2011-08-14Unroll the loop over passesLibravatar Michael Haggerty1-25/+26
The passes no longer share much code, and the unrolled code is easier to understand. Use a new index variable instead of num_attr for the second loop, as we are no longer counting attributes but rather indexing through them. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-14Change while loop into for loopLibravatar Michael Haggerty1-4/+1
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-14Determine the start of the states outside of the pass loopLibravatar Michael Haggerty1-3/+5
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-14Change parse_attr() to take a pointer to struct attr_stateLibravatar Michael Haggerty1-6/+11
parse_attr() only needs access to the attr_state to which it should store its results, not to the whole match_attr structure. This change also removes the need for it to know num_attr. Change its signature accordingly and add a comment. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-14Increment num_attr in parse_attr_line(), not parse_attr()Libravatar Michael Haggerty1-4/+4
num_attr is incremented iff parse_attr() returns non-NULL. So do the counting in parse_attr_line() instead of within parse_attr(). This allows an integer rather than a pointer to an integer to be passed to parse_attr(). Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-14Document struct match_attrLibravatar Michael Haggerty1-0/+14
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-14Add a file commentLibravatar Michael Haggerty1-16/+10
Consolidate here a few general comments plus links to other documentation. Delete a comment with an out-of-date description of the .gitattributes file format. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Rename git_checkattr() to git_check_attr()Libravatar Michael Haggerty1-1/+1
Suggested by: Junio Hamano <gitster@pobox.com> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Allow querying all attributes on a fileLibravatar Michael Haggerty1-0/+28
Add a function, git_all_attrs(), that reports on all attributes that are set on a path. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Remove redundant checkLibravatar Michael Haggerty1-2/+1
bootstrap_attr_stack() also checks whether attr_stack is already set. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Remove redundant call to bootstrap_attr_stack()Libravatar Michael Haggerty1-1/+0
prepare_attr_stack() does the same thing. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Extract a function collect_all_attrs()Libravatar Michael Haggerty1-3/+14
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Teach prepare_attr_stack() to figure out dirlen itselfLibravatar Michael Haggerty1-10/+11
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Provide access to the name attribute of git_attrLibravatar Michael Haggerty1-0/+5
It will be present in any likely future reimplementation, and its availability simplifies other code. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Disallow the empty string as an attribute nameLibravatar Michael Haggerty1-1/+1
Previously, it was possible to have a line like "file.txt =foo" in a .gitattribute file, after which an invocation like "git check-attr '' -- file.txt" would succeed. This patch disallows both constructs. Please note that any existing .gitattributes file that tries to set an empty attribute will now trigger the error message "error: : not a valid attribute name" whereas previously the nonsense was allowed through. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-08-04Remove anachronism from commentLibravatar Michael Haggerty1-4/+2
Setting attributes to arbitrary values ("attribute=value") is now supported, so it is no longer necessary for this comment to justify prohibiting '=' in an attribute name. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-04-22sparse: Fix some "symbol not declared" warningsLibravatar Ramsay Jones1-2/+2
In particular, sparse issues the "symbol 'a_symbol' was not declared. Should it be static?" warnings for the following symbols: attr.c:468:12: 'git_etc_gitattributes' attr.c:476:5: 'git_attr_system' vcs-svn/svndump.c:282:6: 'svndump_read' vcs-svn/svndump.c:417:5: 'svndump_init' vcs-svn/svndump.c:432:6: 'svndump_deinit' vcs-svn/svndump.c:445:6: 'svndump_reset' The symbols in attr.c only require file scope, so we add the static modifier to their declaration. The symbols in vcs-svn/svndump.c are external symbols, and they already have extern declarations in the "svndump.h" header file, so we simply include the header in svndump.c. Signed-off-by: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2011-03-15gitattributes: drop support for GIT_ATTR_NOGLOBALLibravatar Jonathan Nieder1-6/+1
test-lib sets $HOME to protect against pollution from user settings, so setting GIT_ATTR_NOGLOBAL would be redundant. Simplify by eliminating support for that environment variable altogether. GIT_ATTR_NOGLOBAL was introduced in v1.7.4-rc0~208^2 (Add global and system-wide gitattributes, 2010-09-01) as an undocumented feature for use by the test suite. It never ended up being used (neither within git.git nor in other projects). This patch does not affect GIT_ATTR_NOSYSTEM, which should still be useful. Helped-by: Jeff King <peff@peff.net> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-09-01Add global and system-wide gitattributesLibravatar Petr Onderka1-1/+51
Allow gitattributes to be set globally and system wide. This way, settings for particular file types can be set in one place and apply for all user's repositories. The location of system-wide attributes file is $(prefix)/etc/gitattributes. The location of the global file can be configured by setting core.attributesfile. Some parts of the code were copied from the implementation of the same functionality in config.c. Signed-off-by: Petr Onderka <gsvick@gmail.com> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-06-21Merge branch 'eb/core-eol'Libravatar Junio C Hamano1-1/+1
* eb/core-eol: Add "core.eol" config variable Rename the "crlf" attribute "text" Add per-repository eol normalization Add tests for per-repository eol normalization Conflicts: Documentation/config.txt Makefile
2010-05-19Rename the "crlf" attribute "text"Libravatar Eyvind Bernhardsen1-1/+1
As discussed on the list, "crlf" is not an optimal name. Linus suggested "text", which is much better. Signed-off-by: Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-10attr: Expand macros immediately when encountered.Libravatar Henrik Grubbström1-12/+20
When using macros it is otherwise hard to know whether an attribute set by the macro should override an already set attribute. Consider the following .gitattributes file: [attr]mybinary binary -ident * ident foo.bin mybinary bar.bin mybinary ident Without this patch both foo.bin and bar.bin will have the ident attribute set, which is probably not what the user expects. With this patch foo.bin will have an unset ident attribute, while bar.bin will have it set. Signed-off-by: Henrik Grubbström <grubba@grubba.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-10attr: Allow multiple changes to an attribute on the same line.Libravatar Henrik Grubbström1-1/+1
When using macros it isn't inconceivable to have an attribute being set by a macro, and then being reset explicitly. Signed-off-by: Henrik Grubbström <grubba@grubba.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-04-10attr: Fixed debug output for macro expansion.Libravatar Henrik Grubbström1-1/+3
When debug_set() was called during macro expansion, it received a pointer to a struct git_attr rather than a string. Signed-off-by: Henrik Grubbström <grubba@grubba.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2010-01-16git_attr(): fix function signatureLibravatar Junio C Hamano1-3/+8
The function took (name, namelen) as its arguments, but all the public callers wanted to pass a full string. Demote the counted-string interface to an internal API status, and allow public callers to just pass the string to the function. Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-30attr: plug minor memory leakLibravatar René Scharfe1-0/+2
Free the memory allocated for struct strbuf pathbuf when we're done. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-06-18Fix big left-shifts of unsigned charLibravatar Linus Torvalds1-2/+1
Shifting 'unsigned char' or 'unsigned short' left can result in sign extension errors, since the C integer promotion rules means that the unsigned char/short will get implicitly promoted to a signed 'int' due to the shift (or due to other operations). This normally doesn't matter, but if you shift things up sufficiently, it will now set the sign bit in 'int', and a subsequent cast to a bigger type (eg 'long' or 'unsigned long') will now sign-extend the value despite the original expression being unsigned. One example of this would be something like unsigned long size; unsigned char c; size += c << 24; where despite all the variables being unsigned, 'c << 24' ends up being a signed entity, and will get sign-extended when then doing the addition in an 'unsigned long' type. Since git uses 'unsigned char' pointers extensively, we actually have this bug in a couple of places. I may have missed some, but this is the result of looking at git grep '[^0-9 ][ ]*<<[ ][a-z]' -- '*.c' '*.h' git grep '<<[ ]*24' which catches at least the common byte cases (shifting variables by a variable amount, and shifting by 24 bits). I also grepped for just 'unsigned char' variables in general, and converted the ones that most obviously ended up getting implicitly cast immediately anyway (eg hash_name(), encode_85()). In addition to just avoiding 'unsigned char', this patch also tries to use a common idiom for the delta header size thing. We had three different variations on it: "& 0x7fUL" in one place (getting the sign extension right), and "& ~0x80" and "& 0x7f" in two other places (not getting it right). Apart from making them all just avoid using "unsigned char" at all, I also unified them to then use a simple "& 0x7f". I considered making a sparse extension which warns about doing implicit casts from unsigned types to signed types, but it gets rather complex very quickly, so this is just a hack. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-05-01Fix a bunch of pointer declarations (codestyle)Libravatar Felipe Contreras1-2/+2
Essentially; s/type* /type */ as per the coding guidelines. Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-04-17attr: add GIT_ATTR_INDEX "direction"Libravatar Nguyễn Thái Ngọc Duy1-3/+9
This instructs attr mechanism, not to look into working .gitattributes at all. Needed by tools that does not handle working directory, such as "git archive". Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2009-03-13Read attributes from the index that is being checked outLibravatar Junio C Hamano1-18/+55
Traditionally we used .gitattributes file from the work tree if exists, and otherwise read from the index as a fallback. When switching to a branch that has an updated .gitattributes file, and entries in it give different attributes to other paths being checked out, we should instead read from the .gitattributes in the index. This breaks a use case of fixing incorrect entries in the .gitattributes in the work tree (without adding it to the index) and checking other paths out, though. $ edit .gitattributes ;# mark foo.dat as binary $ rm foo.dat $ git checkout foo.dat Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-07-16Fix buffer overflow in prepare_attr_stackLibravatar Dmitry Potapov1-6/+9
If PATH_MAX on your system is smaller than a path stored in the git repo, it may cause the buffer overflow in prepare_attr_stack. Signed-off-by: Dmitry Potapov <dpotapov@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-06-09Ignore .gitattributes in bare repositoriesLibravatar René Scharfe1-21/+25
Attributes can be specified at three different places: the internal table of default values, the file $GIT_DIR/info/attributes and files named .gitattributes in the work tree. Since bare repositories don't have a work tree, git should ignore any .gitattributes files there. This patch makes git do that, so the only way left for a user to specify attributes in a bare repository is the file info/attributes (in addition to changing the defaults and recompiling). In addition, git-check-attr is now allowed to run without a work tree. Like any user of the code in attr.c, it ignores the .gitattributes files when run in a bare repository. It can still read from info/attributes. Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx> Signed-off-by: Junio C Hamano <gitster@pobox.com>
2008-04-22gitattributes: Fix subdirectory attributes specified from root directoryLibravatar Matthew Ogilvie1-1/+3
Signed-off-by: Matthew Ogilvie <mmogilvi_git@miniinfo.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>