From da320b470d829478840ab24769b22afd45462c52 Mon Sep 17 00:00:00 2001
From: Ondrej Nosek <onosek@redhat.com>
Date: Apr 26 2019 11:44:07 +0000
Subject: Ignore files in a cloned repository


Git will ignore automatically generated files. Ignored patterns can be
specified in rhpkg/fedpkg config. Patterns are applied in
'.git/info/exclude' file only when repository is cloned. And changes are
valid only for local repository.

JIRA: COMPOSE-2794
Fixes: #355

Signed-off-by: Ondrej Nosek <onosek@redhat.com>

---

diff --git a/pyrpkg/__init__.py b/pyrpkg/__init__.py
index 23b1ed7..7ad78d1 100644
--- a/pyrpkg/__init__.py
+++ b/pyrpkg/__init__.py
@@ -96,7 +96,8 @@ class Commands(object):
                  build_client,
                  koji_config_type='config', user=None,
                  dist=None, target=None, quiet=False,
-                 distgit_namespaced=False, realms=None, lookaside_namespaced=False):
+                 distgit_namespaced=False, realms=None, lookaside_namespaced=False,
+                 git_excludes=None):
         """Init the object and some configuration details."""
 
         # Path to operate on, most often pwd
@@ -215,6 +216,8 @@ class Commands(object):
         self.module_api_url = None
         # Namespaces for which retirement is blocked by default.
         self.block_retire_ns = ['rpms']
+        # Git excludes patterns
+        self.git_excludes = git_excludes or []
 
     # Define properties here
     # Properties allow us to "lazy load" various attributes, which also means
@@ -1543,6 +1546,8 @@ class Commands(object):
         conf_git = git.Git(os.path.join(path, git_dir))
         self._clone_config(conf_git, repo)
 
+        self._add_git_excludes(os.path.join(path, git_dir))
+
         return
 
     def get_base_repo(self, repo):
@@ -1652,6 +1657,20 @@ class Commands(object):
                 if confline:
                     conf_git.config(*confline.split())
 
+    def _add_git_excludes(self, conf_dir):
+        """
+        Add a list of patterns from config into the config file in a git
+        repository. This list excludes some files or dirs to be tracked by
+        git. This list usually includes files that are automatically generated.
+        These changes are valid just for local git repository.
+        """
+        git_excludes_path = os.path.join(conf_dir, '.git/info/exclude')
+        git_excludes = GitIgnore(git_excludes_path)
+        for item in self.git_excludes:
+            git_excludes.add(item)
+        git_excludes.write()
+        self.log.debug('Git-excludes patterns were added into %s' % git_excludes_path)
+
     def commit(self, message=None, file=None, files=[], signoff=False):
         """Commit changes to a repository (optionally found at path)
 
diff --git a/pyrpkg/cli.py b/pyrpkg/cli.py
index 400ebd1..004d2aa 100644
--- a/pyrpkg/cli.py
+++ b/pyrpkg/cli.py
@@ -266,6 +266,11 @@ class cliClient(object):
                 'Format argument module is deprecated in anongiturl. '
                 'Please use "repo" instead.')
 
+        # Read line separated list of git excludes patterns
+        git_excludes = [excl
+                        for excl in items.get("git_excludes", '').split('\n')
+                        if excl]
+
         # Create the cmd object
         self._cmd = self.site.Commands(self.args.path,
                                        items['lookaside'],
@@ -283,7 +288,8 @@ class cliClient(object):
                                        quiet=self.args.q,
                                        distgit_namespaced=dg_namespaced,
                                        realms=realms,
-                                       lookaside_namespaced=la_namespaced
+                                       lookaside_namespaced=la_namespaced,
+                                       git_excludes=git_excludes
                                        )
 
         if self.args.module_name:
diff --git a/tests/commands/__init__.py b/tests/commands/__init__.py
index 46cbdef..0c121a6 100644
--- a/tests/commands/__init__.py
+++ b/tests/commands/__init__.py
@@ -33,6 +33,11 @@ class CommandTestCase(unittest.TestCase):
             bz.default-component %(module)s
             sendemail.to %(module)s-owner@fedoraproject.org
         '''
+        self.git_excludes = [
+            'i386/',
+            'noarch/',
+            'build*.log',
+        ]
         self.user = 'TODO'
         self.dist = 'TODO'
         self.target = 'TODO'
diff --git a/tests/commands/test_clone.py b/tests/commands/test_clone.py
index 4cb744e..f32ffef 100644
--- a/tests/commands/test_clone.py
+++ b/tests/commands/test_clone.py
@@ -72,6 +72,29 @@ class CommandCloneTestCase(CommandTestCase):
 
         shutil.rmtree(altpath)
 
+    def test_clone_anonymous_git_excludes(self):
+        self.make_new_git(self.module)
+
+        altpath = tempfile.mkdtemp(prefix='rpkg-tests.')
+
+        cmd = pyrpkg.Commands(self.path, self.lookaside, self.lookasidehash,
+                              self.lookaside_cgi, self.gitbaseurl,
+                              self.anongiturl, self.branchre, self.kojiprofile,
+                              self.build_client, self.user, self.dist,
+                              self.target, self.quiet,
+                              git_excludes=self.git_excludes)
+        cmd.clone(self.module, anon=True)
+
+        moduledir = os.path.join(self.path, self.module)
+        self.assertTrue(os.path.isfile(os.path.join(moduledir, '.git/info/exclude')))
+
+        with open(os.path.join(moduledir, '.git/info/exclude')) as git_exclude_file:
+            all_excludes = git_exclude_file.read()
+            for pattern in self.git_excludes:
+                self.assertIn(pattern, all_excludes)
+
+        shutil.rmtree(altpath)
+
     def test_clone_anonymous_with_branch(self):
         self.make_new_git(self.module,
                           branches=['rpkg-tests-1', 'rpkg-tests-2'])

