summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrej Shadura <andrew.shadura@collabora.co.uk>2021-02-07 19:30:12 +0100
committerGuido Günther <agx@sigxcpu.org>2021-03-11 12:48:47 +0100
commit8e0e7ccc300507bc2a65814684aa570aa7633a33 (patch)
tree84f9285a80f4ea6803d8474971e8aea66d92b26a
parent3fa9f4d35c38fcf0fdd387e6e0a0199a14a5160e (diff)
repo_setup: Add check/setup_gitattributes
setup_gitattributes() sets up .git/info/attributes in a way to prevent transformations from interfering with packaging, because the working tree files can differ from the Git revision history (and from the source packages). Similar functionality has been implemented by dgit and git-deborig, so we try to stay compatible and re-use the name of the attribute macro. Since dgit doesn’t disable export-subst and export-ignore, which may interfere with export-orig, we add this on top the same way git-deborig does. dgit used to have an older preset missing some of the attributes, so if we find those, we disable them. The user, should they choose so, still can re-enable the attributes disabled in this way by adding more specific rules further in the .git/info/attributes file. Signed-off-by: Andrej Shadura <andrew.shadura@collabora.co.uk>
-rw-r--r--gbp/scripts/common/repo_setup.py94
1 files changed, 94 insertions, 0 deletions
diff --git a/gbp/scripts/common/repo_setup.py b/gbp/scripts/common/repo_setup.py
index d76b585c..50e9cbf1 100644
--- a/gbp/scripts/common/repo_setup.py
+++ b/gbp/scripts/common/repo_setup.py
@@ -1,6 +1,8 @@
# vim: set fileencoding=utf-8 :
#
# (C) 2006-2011, 2016 Guido Günther <agx@sigxcpu.org>
+# (C) 2021 Andrej Shadura <andrew@shadura.me>
+# (C) 2021 Collabora Limited
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
@@ -18,6 +20,10 @@
"""Common repository setup functionality."""
import os
+import re
+import gbp.log
+
+from pathlib import Path
def set_user_name_and_email(repo_user, repo_email, repo):
@@ -28,3 +34,91 @@ def set_user_name_and_email(repo_user, repo_email, repo):
if repo_email == 'DEBIAN':
if os.getenv('DEBEMAIL'):
repo.set_user_email(os.getenv('DEBEMAIL'))
+
+
+def check_gitattributes(repo, treeish) -> bool:
+ """
+ Verify the treeish doesn’t contain non-empty .gitattributes files.
+ """
+ for mode, _type, sha1, size, path in repo.list_tree(treeish, recurse=True, sizes=True):
+ if size == 0:
+ continue
+ if path == b'.gitattributes' or path.endswith(b'/.gitattributes'):
+ gbp.log.debug("Found non-empty .gitattributes: %s" % path)
+ return False
+ return True
+
+
+dgit_attr_macro_re = re.compile(r'^\[attr\]dgit-defuse-attrs\s')
+dgit_attr_macro_defn = '-text -eol -crlf -ident -filter -working-tree-encoding'
+attr_glob_defns = {
+ 'dgit-defuse-attrs',
+ '-export-subst',
+ '-export-ignore',
+}
+
+
+def is_gitattributes_set_up(repo) -> bool:
+ """
+ Return True if git attributes have been set up correctly:
+ * dgit-defuse-attrs macro exists
+ * dgit-defuse-attrs includes attributes we’re interested in
+ * dgit-defuse-attrs is enabled for *
+ * export-subst and export-ignore are unset for *
+ """
+ gitattrs = Path(repo.git_dir) / 'info' / 'attributes'
+ if not gitattrs.exists():
+ return False
+ dgit_macro_present = False
+ attrs = set()
+ for line in gitattrs.read_text().splitlines():
+ if dgit_attr_macro_re.match(line):
+ gbp.log.debug("Found Git attribute macro: %s" % line)
+ dgit_macro_present = line.endswith(dgit_attr_macro_defn)
+ continue
+ attr = line.split()
+ if attr[0] == '*' and len(attr) == 2:
+ attrs.add(attr[1])
+ gbp.log.debug("Found global Git attributes: %s" % ', '.join(attrs))
+ return dgit_macro_present and attrs >= attr_glob_defns
+
+
+def setup_gitattributes(repo, treeish='HEAD'):
+ """
+ Setup .git/info/attributes in a way to prevent transformations from interfering
+ with packaging, because the working tree files can differ from the Git revision
+ history (and from the source packages).
+
+ Similar functionality has been implemented by dgit and git-deborig, so we try
+ to stay compatible and re-use the name of the attribute macro. Since dgit doesn’t
+ disable export-subst and export-ignore, which may interfere with export-orig, we
+ add this on top the same way git-deborig does.
+ """
+ if is_gitattributes_set_up(repo):
+ return
+ gbp.log.debug("Configuring Git attributes")
+ gitattrs = Path(repo.git_dir) / 'info' / 'attributes'
+ new_attributes = []
+ if not gitattrs.exists():
+ gitattrs.parent.mkdir(exist_ok=True)
+ else:
+ for line in gitattrs.read_text().splitlines():
+ attr = line.split()
+ if attr[0] == '*' and len(attr) == 2:
+ if attr[1] in attr_glob_defns:
+ continue
+ if dgit_attr_macro_re.match(line):
+ new_attributes += [
+ "# Old dgit macro disabled:",
+ "# %s" % line,
+ ]
+ gbp.log.debug("Disabling old dgit macro: '%s'" % line)
+ else:
+ new_attributes.append(line)
+ new_attributes += [
+ "# Added by git-buildpackage to disable .gitattributes found in the upstream tree",
+ "[attr]dgit-defuse-attrs %s" % dgit_attr_macro_defn,
+ ] + ['* %s' % attr for attr in attr_glob_defns]
+ with gitattrs.with_suffix('.new') as newattrs:
+ newattrs.write_text('\n'.join(new_attributes))
+ newattrs.rename(gitattrs)