From: Kristian Amlie <kristian.amlie@nokia.com>
To: git@vger.kernel.org
Cc: Kristian Amlie <kristian.amlie@nokia.com>
Subject: [PATCH 2/2] Make Git respect changes to .gitattributes during checkout.
Date: Thu, 12 Mar 2009 10:36:15 +0100 [thread overview]
Message-ID: <1236850575-27973-3-git-send-email-kristian.amlie@nokia.com> (raw)
In-Reply-To: <1236850575-27973-2-git-send-email-kristian.amlie@nokia.com>
We do this by popping off elements on the attribute stack, until we
reach the level where a new .gitattributes was checked out. The next
time someone calls git_checkattr(), it will reconstruct the
attributes from that point.
---
attr.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++----------
attr.h | 1 +
entry.c | 23 ++++++++++++++++++++
3 files changed, 84 insertions(+), 12 deletions(-)
diff --git a/attr.c b/attr.c
index 17f6a4d..7deb51a 100644
--- a/attr.c
+++ b/attr.c
@@ -455,6 +455,23 @@ static void bootstrap_attr_stack(void)
}
}
+static void pop_attr_stack(const char *path, int dirlen)
+{
+ struct attr_stack *elem;
+ while (attr_stack && attr_stack->origin) {
+ int namelen = strlen(attr_stack->origin);
+
+ elem = attr_stack;
+ if (namelen <= dirlen &&
+ !strncmp(elem->origin, path, namelen))
+ break;
+
+ debug_pop(elem);
+ attr_stack = elem->prev;
+ free_attr_elem(elem);
+ }
+}
+
static void prepare_attr_stack(const char *path, int dirlen)
{
struct attr_stack *elem, *info;
@@ -489,18 +506,7 @@ static void prepare_attr_stack(const char *path, int dirlen)
* Pop the ones from directories that are not the prefix of
* the path we are checking.
*/
- while (attr_stack && attr_stack->origin) {
- int namelen = strlen(attr_stack->origin);
-
- elem = attr_stack;
- if (namelen <= dirlen &&
- !strncmp(elem->origin, path, namelen))
- break;
-
- debug_pop(elem);
- attr_stack = elem->prev;
- free_attr_elem(elem);
- }
+ pop_attr_stack(path, dirlen);
/*
* Read from parent directories and push them down
@@ -642,3 +648,45 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
return 0;
}
+
+void git_attr_invalidate_path(const char *path)
+{
+ int dirlen;
+ const char *cp;
+ struct attr_stack *info, *elem;
+
+ bootstrap_attr_stack();
+
+ /*
+ * Pop the "info" one that is always at the top of the stack.
+ */
+ info = attr_stack;
+ attr_stack = info->prev;
+
+ cp = strrchr(path, '/');
+ dirlen = cp ? cp - path : 0;
+ /* Pop everything up to, and including, path. */
+ pop_attr_stack(path, dirlen);
+
+ if (!strcmp(path, "") && attr_stack->origin && !strcmp(attr_stack->origin, "")) {
+ /* Special handling when the root attributes must be invalidated. */
+ elem = attr_stack;
+ debug_pop(elem);
+ attr_stack = elem->prev;
+ free_attr_elem(elem);
+
+ if (!is_bare_repository()) {
+ elem = read_attr(GITATTRIBUTES_FILE, 1);
+ elem->origin = strdup("");
+ elem->prev = attr_stack;
+ attr_stack = elem;
+ debug_push(elem);
+ }
+ }
+
+ /*
+ * Finally push the "info" one at the top of the stack.
+ */
+ info->prev = attr_stack;
+ attr_stack = info;
+}
diff --git a/attr.h b/attr.h
index f1c2038..8f4135b 100644
--- a/attr.h
+++ b/attr.h
@@ -30,5 +30,6 @@ struct git_attr_check {
};
int git_checkattr(const char *path, int, struct git_attr_check *);
+void git_attr_invalidate_path(const char *path);
#endif /* ATTR_H */
diff --git a/entry.c b/entry.c
index 05aa58d..121c979 100644
--- a/entry.c
+++ b/entry.c
@@ -1,6 +1,7 @@
#include "cache.h"
#include "blob.h"
#include "dir.h"
+#include "attr.h"
static void create_directories(const char *path, const struct checkout *state)
{
@@ -91,6 +92,9 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
{
int fd;
long wrote;
+ int gitattrlen;
+ int pathlen;
+ char *inv_path;
switch (ce->ce_mode & S_IFMT) {
char *new;
@@ -171,6 +175,25 @@ static int write_entry(struct cache_entry *ce, char *path, const struct checkout
return error("git checkout-index: unknown file mode for %s", path);
}
+ gitattrlen = strlen(GITATTRIBUTES_FILE);
+ pathlen = strlen(path);
+ if (!strncmp(path + pathlen - gitattrlen, GITATTRIBUTES_FILE, gitattrlen)) {
+ /* Invalidate attributes if a new .gitattributes file was checked out. */
+ inv_path = strrchr(path, '/');
+ if (!inv_path) {
+ pathlen = 0;
+ inv_path = xmalloc(1);
+ *inv_path = '\0';
+ } else {
+ pathlen = inv_path - path;
+ inv_path = xmalloc(pathlen + 1);
+ strncpy(inv_path, path, pathlen);
+ inv_path[pathlen] = '\0';
+ }
+ git_attr_invalidate_path(inv_path);
+ free(inv_path);
+ }
+
if (state->refresh_cache) {
struct stat st;
lstat(ce->name, &st);
--
1.6.2.105.g16bc7.dirty
next prev parent reply other threads:[~2009-03-12 9:38 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-01-28 15:25 Honoring a checked out gitattributes file Kristian Amlie
2009-01-28 16:44 ` Michael J Gruber
2009-01-28 17:25 ` Kristian Amlie
2009-01-30 13:00 ` Kristian Amlie
2009-01-30 13:00 ` [PATCH] Add a test for checking whether gitattributes is honored by checkout Kristian Amlie
2009-03-12 9:36 ` Honoring a checked out gitattributes file Kristian Amlie
2009-03-12 9:36 ` [PATCH 1/2] Add a test for checking whether gitattributes is honored by checkout Kristian Amlie
2009-03-12 9:36 ` Kristian Amlie [this message]
2009-03-12 9:59 ` [PATCH 2/2] Make Git respect changes to .gitattributes during checkout Johannes Sixt
2009-03-12 10:23 ` Kristian Amlie
2009-03-13 13:24 ` Honoring a checked out gitattributes file Kristian Amlie
2009-03-13 13:24 ` [PATCH 1/2] Add a test for checking whether gitattributes is honored by checkout Kristian Amlie
2009-03-13 13:24 ` [PATCH 2/2] Make Git respect changes to .gitattributes during checkout Kristian Amlie
2009-03-14 4:17 ` Junio C Hamano
2009-03-19 15:42 ` Kristian Amlie
2009-03-19 21:06 ` Junio C Hamano
2009-03-20 8:11 ` Kristian Amlie
2009-03-20 9:32 ` [PATCH] Add a test for checking whether gitattributes is honored by checkout Kristian Amlie
2009-03-14 4:36 ` [PATCH 1/2] " Junio C Hamano
2009-03-12 9:47 ` Matthieu Moy
2009-03-12 9:53 ` Kristian Amlie
2009-01-28 17:55 ` Honoring a checked out gitattributes file Jeff King
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1236850575-27973-3-git-send-email-kristian.amlie@nokia.com \
--to=kristian.amlie@nokia.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).