Explorar o código

WIP: Add Git attributes parser

Signed-off-by: Andrej Shadura <andrew.shadura@collabora.co.uk>
Andrej Shadura %!s(int64=3) %!d(string=hai) anos
pai
achega
33691f9a04
Modificáronse 1 ficheiros con 95 adicións e 0 borrados
  1. 95 0
      dulwich/attrs.py

+ 95 - 0
dulwich/attrs.py

@@ -0,0 +1,95 @@
+# attrs.py -- Git attributes for dulwich
+# Copyright (C) 2019-2020 Collabora Ltd
+# Copyright (C) 2019-2020 Andrej Shadura <andrew.shadura@collabora.co.uk>
+#
+# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
+# General Public License as public by the Free Software Foundation; version 2.0
+# or (at your option) any later version. You can redistribute it and/or
+# modify it under the terms of either of these two licenses.
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# You should have received a copy of the licenses; if not, see
+# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
+# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
+# License, Version 2.0.
+#
+
+"""Parse .gitattributes file.
+"""
+
+import sys
+from typing import (
+    Generator,
+    IO,
+    List,
+    Mapping,
+    Optional,
+    Sequence,
+    Tuple,
+    Union,
+)
+
+
+AttributeValue = Union[str, bool, None]
+
+
+def _parse_attr(attr: str) -> Tuple[str, AttributeValue]:
+    """Parse a git attribute into its value:
+
+    >>> _parse_attr('attr')
+    ('attr', True)
+    >>> _parse_attr('-attr')
+    ('attr', False)
+    >>> _parse_attr('!attr')
+    ('attr', None)
+    >>> _parse_attr('attr=text')
+    ('attr', 'text')
+    """
+    if attr.startswith('!'):
+        return attr[1:], None
+    if attr.startswith('-'):
+        return attr[1:], False
+    if '=' not in attr:
+        return attr, True
+    return tuple(attr.split('='))
+
+
+def parse_git_attributes(f: IO[bytes]) -> Generator[Tuple[bytes, Mapping[str, AttributeValue]], None, None]:
+    """Parse a Git attributes string
+
+    Args:
+      f: File-like object to read bytes from
+    Returns:
+      List of patterns and corresponding patterns in the order or them being encountered
+    >>> from io import BytesIO
+    >>> list(parse_git_attributes(BytesIO(b'''*.tar.* filter=lfs diff=lfs merge=lfs -text
+    ... 
+    ... # store signatures in Git
+    ... *.tar.*.asc -filter -diff merge=binary -text
+    ... 
+    ... # store .dsc verbatim
+    ... *.dsc -filter !diff merge=binary !text
+    ... '''))) #doctest: +NORMALIZE_WHITESPACE
+    [(b'*.tar.*', {'filter': 'lfs', 'diff': 'lfs', 'merge': 'lfs', 'text': False}),
+     (b'*.tar.*.asc', {'filter': False, 'diff': False, 'merge': 'binary', 'text': False}),
+     (b'*.dsc', {'filter': False, 'diff': None, 'merge': 'binary', 'text': None})]
+    """
+    for line in f:
+        line = line.strip()
+
+        # Ignore blank lines, they're used for readability.
+        if not line:
+            continue
+
+        if line.startswith(b'#'):
+            # Comment
+            continue
+
+        pattern, *attrs = line.split()
+
+        yield (pattern, {k: v for k, v in (_parse_attr(a.decode()) for a in attrs)})