Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package git-deps for openSUSE:Factory 
checked in at 2024-07-22 17:14:53
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/git-deps (Old)
 and      /work/SRC/openSUSE:Factory/.git-deps.new.17339 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "git-deps"

Mon Jul 22 17:14:53 2024 rev:5 rq:1188586 version:1.1.0+git.1696898573.89d51e8

Changes:
--------
--- /work/SRC/openSUSE:Factory/git-deps/git-deps.changes        2022-09-26 
18:48:37.044101139 +0200
+++ /work/SRC/openSUSE:Factory/.git-deps.new.17339/git-deps.changes     
2024-07-22 17:15:10.886497252 +0200
@@ -1,0 +2,65 @@
+Thu Jul 18 14:49:09 UTC 2024 - mc...@cepl.eu
+
+- Update to version 1.1.0+git.1696898573.89d51e8:
+  * Only use pygit2's blame via opt-in
+  * Blame via pygit2 instead of subprocess
+  * Fix deps fetching on the root commit
+  * Start test suite of running git-deps on itself
+  * Remove dependency to six. Closes #115
+  * Remove Travis config
+  * Upgrade setuptools
+  * Create CI.yml
+  * Import `safe_join` from `werkzeug.security`
+  * Drop support for Python 3.6
+  * Drop setuptools-markdown
+  * Handle server port in use error more gracefully (#88)
+  * Fix publishing procedure
+  * Expand AUTHORS.rst
+  * Remove sphinx.ext.pngmath
+  * Add maintainer-guide to the docs
+  * Be stricter with docs
+  * Update sphinx docs location
+  * Update CHANGES.rst
+  * Add flake8 to Travis
+  * Fix some flake8 issues
+  * Don't totally ignore KeyboardInterrupt
+  * Improve HTML installation instructions slightly
+  * Update INSTALL.md for Python 3.x (#98)
+  * Update tox.ini for newer Pythons
+  * Fix Travis builds (#73)
+  * Use line-buffering on output (#87)
+  * Bump jquery from 3.0.0 to 3.5.0 in /git_deps/html
+- Remove upstreamed patches:
+  - Fix-issue-with-unbuffered-text-I-O-under-python3.patch
+- Add compatibility patches:
+  - no-pkg-resources.patch
+  - pygit2-1.15.0.patch (from gh#aspiers/git-deps!129)
+
+-------------------------------------------------------------------
+Tue Jul 18 09:45:54 UTC 2023 - mc...@cepl.eu
+
+- Update to version 1.1.0+git.1655802074.8cafb5c:
+  * Import `safe_join` from `werkzeug.security`
+  * Drop support for Python 3.6
+  * Drop setuptools-markdown
+  * Handle server port in use error more gracefully (#88)
+  * Fix publishing procedure
+  * Expand AUTHORS.rst
+  * Remove sphinx.ext.pngmath
+  * Add maintainer-guide to the docs
+  * Be stricter with docs
+  * Update sphinx docs location
+  * Update CHANGES.rst
+  * Add flake8 to Travis
+  * Fix some flake8 issues
+  * Don't totally ignore KeyboardInterrupt
+  * Improve HTML installation instructions slightly
+  * Update INSTALL.md for Python 3.x (#98)
+  * Update tox.ini for newer Pythons
+  * Fix Travis builds (#73)
+  * Use line-buffering on output (#87)
+  * Bump jquery from 3.0.0 to 3.5.0 in /git_deps/html
+- Remove upstreamed Fix-issue-with-unbuffered-text-I-O-under-python3.patch
+- Switch package to be managed by SCM.
+
+-------------------------------------------------------------------

Old:
----
  Fix-issue-with-unbuffered-text-I-O-under-python3.patch
  git-deps-1.0.2+git.1559732444.7c75531.tar.xz

New:
----
  _scmsync.obsinfo
  build.specials.obscpio
  git-deps-1.1.0+git.1696898573.89d51e8.tar.xz
  no-pkg-resources.patch
  pygit2-1.15.0.patch

BETA DEBUG BEGIN:
  Old:- Remove upstreamed patches:
  - Fix-issue-with-unbuffered-text-I-O-under-python3.patch
- Add compatibility patches:
BETA DEBUG END:

BETA DEBUG BEGIN:
  New:- Add compatibility patches:
  - no-pkg-resources.patch
  - pygit2-1.15.0.patch (from gh#aspiers/git-deps!129)
  New:  - no-pkg-resources.patch
  - pygit2-1.15.0.patch (from gh#aspiers/git-deps!129)
BETA DEBUG END:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ git-deps.spec ++++++
--- /var/tmp/diff_new_pack.7Bnzan/_old  2024-07-22 17:15:12.198550012 +0200
+++ /var/tmp/diff_new_pack.7Bnzan/_new  2024-07-22 17:15:12.202550172 +0200
@@ -16,29 +16,40 @@
 #
 
 
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define skip_python2 1
 Name:           git-deps
-Version:        1.0.2+git.1559732444.7c75531
+Version:        1.1.0+git.1696898573.89d51e8
 Release:        0
 Summary:        Tool to analyze git deps
 License:        GPL-2.0-only
 Group:          Development/Tools/Version Control
 URL:            https://github.com/aspiers/git-deps
 Source:         %{name}-%{version}.tar.xz
+# PATCH-FIX-UPSTREAM dont-use-st-markdown.patch gh#aspiers/git-deps!118 
mc...@suse.com
+# update syntax to the current levels and eliminate (almost) setup.py
 Patch0:         dont-use-st-markdown.patch
-Patch1:         Fix-issue-with-unbuffered-text-I-O-under-python3.patch
+# PATCH-FIX-UPSTREAM pygit2-1.15.0.patch gh#aspiers/git-deps!129 mc...@suse.com
+# make compatible with pygit2 1.15.0
+Patch1:         pygit2-1.15.0.patch
+# PATCH-FIX-UPSTREAM no-pkg-resources.patch gh#aspiers/git-deps!131 
mc...@suse.com
+# Don't depend on pkg_resources
+Patch2:         no-pkg-resources.patch
 BuildRequires:  fdupes
+BuildRequires:  git
 BuildRequires:  python-rpm-macros
 BuildRequires:  python3-pip
 BuildRequires:  python3-pygit2
-BuildRequires:  python3-setuptools
+# Because of version = attr: package.__version__
+BuildRequires:  python3-setuptools >= 46.4.0
 BuildRequires:  python3-wheel
+BuildRequires:  python3-pytest
+# BuildRequires:  python3-certifi
 Requires:       python3-pygit2
 # for html subpackage
 Requires:       python3-Flask
 #Requires:       nodejs-browserify # broken/missing
 Requires:       npm
+Requires:       git
 BuildArch:      noarch
 
 %description
@@ -57,22 +68,30 @@
 %autosetup -p1 -n %{name}-%{version}
 
 %build
-# https://github.com/aspiers/git-deps/issues/115
-sed -i '/six/d' setup.py
-python3 -s setup.py build
+%python3_pyproject_wheel
 
 %install
-python3 -s setup.py install -O1 --skip-build --force --root %{buildroot} 
--prefix %{_prefix}
-%python_expand %fdupes %{buildroot}%{python_sitelib}
+%python3_pyproject_install
+install -D -m 755 %{buildroot}%{python3_sitelib}/git_deps/handler.py \
+    %{buildroot}%{_bindir}/gitfile-handler
+%python3_fix_shebang
+%fdupes %{buildroot}%{python3_sitelib}
+
+%check
+# Test doesn't work with tarball, requires .git/ directory with full history
+# # because of gh#libgit2/pygit2$1311
+# export PYTEST_ADDOPTS="--ignore tests/test_GitUtils.py"
+# %%python3_pytest
 
 %files
-%{_bindir}/git-deps
-%{_bindir}/git-fixup
-%{_bindir}/gitfile-handler
-%{python_sitelib}/git_deps*
 %license LICENSE.txt
 %doc AUTHORS.rst CONTRIBUTING.md CHANGES.rst README.md USAGE.md
 %doc HISTORY.md USE-CASES.md
+%{_bindir}/git-deps
+# %%{_bindir}/git-fixup
+%{_bindir}/gitfile-handler
+%{python3_sitelib}/git_deps
+%{python3_sitelib}/git_deps-1.1.0*-info
 
 %files html
 %doc docs

++++++ _scmsync.obsinfo ++++++
mtime: 1721385311
commit: 031f5590d6583bb770776dc0679ffacdd7c4be6ead767781ce448da129f8ac92
url: https://src.opensuse.org/mcepl_pkgs/git-deps.git
revision: 031f5590d6583bb770776dc0679ffacdd7c4be6ead767781ce448da129f8ac92

++++++ _service ++++++
--- /var/tmp/diff_new_pack.7Bnzan/_old  2024-07-22 17:15:12.258552425 +0200
+++ /var/tmp/diff_new_pack.7Bnzan/_new  2024-07-22 17:15:12.262552585 +0200
@@ -1,16 +1,16 @@
 <services>
-    <service name="tar_scm" mode="disabled">
-        <param name="versionprefix">1.0.2+git</param>
+    <service name="tar_scm" mode="manual">
+        <param name="versionprefix">1.1.0+git</param>
         <param name="url">https://github.com/aspiers/git-deps</param>
         <param name="scm">git</param>
         <param name="exclude">.git*</param>
         <param name="changesgenerate">enable</param>
         <param name="changesauthor">mc...@cepl.eu</param>
     </service>
-    <service mode="disabled" name="recompress">
+    <service mode="manual" name="recompress">
         <param name="file">*.tar</param>
         <param name="compression">xz</param>
     </service>
-    <service mode="disabled" name="set_version"/>
+    <service mode="manual" name="set_version"/>
 </services>
 

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.7Bnzan/_old  2024-07-22 17:15:12.282553390 +0200
+++ /var/tmp/diff_new_pack.7Bnzan/_new  2024-07-22 17:15:12.286553550 +0200
@@ -1,6 +1,6 @@
 <servicedata>
 <service name="tar_scm">
                 <param name="url">https://github.com/aspiers/git-deps</param>
-              <param 
name="changesrevision">7c7553151dda8f9abd4c1dc9f0aa8a4c05f65d9a</param></service></servicedata>
+              <param 
name="changesrevision">89d51e87a3fe4bdcb1efabbe7a4923958998a61c</param></service></servicedata>
 (No newline at EOF)
 

++++++ dont-use-st-markdown.patch ++++++
--- /var/tmp/diff_new_pack.7Bnzan/_old  2024-07-22 17:15:12.302554194 +0200
+++ /var/tmp/diff_new_pack.7Bnzan/_new  2024-07-22 17:15:12.306554355 +0200
@@ -1,69 +1,83 @@
+---
+ setup.cfg            |    6 ++++--
+ setup.py             |   25 +------------------------
+ tests/create-repo.sh |    1 -
+ 3 files changed, 5 insertions(+), 27 deletions(-)
+
+--- a/setup.cfg
++++ b/setup.cfg
+@@ -1,11 +1,13 @@
+ [metadata]
+ name = git-deps
++version = 1.1.0
+ summary = automatically detect dependencies between git commits
+ author = Adam Spiers
+ author_email = g...@adamspiers.org
+ license = GPL-2+
+ home_page = https://github.com/aspiers/git-deps
+-description_file = README.md
++long_description = file: README.md
++long_description_content_type = text/markdown
+ classifier =
+     Development Status :: 4 - Beta
+     Environment :: Console
+@@ -33,6 +35,7 @@ data_files =
+ [options]
+ packages =
+     git_deps
++requires = Sphinx
+
+ [options.entry_points]
+ console_scripts =
+@@ -48,7 +51,6 @@ addopts = tests
+ # e.g. --cov-report html (or xml) for html/xml output or --junitxml junit.xml
+ # in order to write a coverage file that can be read by Jenkins.
+ addopts =
+-    --cov git_deps --cov-report term-missing
+     --verbose
+
+ [aliases]
 --- a/setup.py
 +++ b/setup.py
-@@ -8,21 +8,50 @@
-     http://pyscaffold.readthedocs.org/
- """
- 
-+import os
- import sys
+@@ -1,29 +1,6 @@
+ #!/usr/bin/env python
+ # -*- coding: utf-8 -*-
+-"""
+-    Setup file for git_deps.
+-
+-    This file was generated with PyScaffold, a tool that easily
+-    puts up a scaffold for your new Python project. Learn more under:
+-    http://pyscaffold.readthedocs.org/
+-"""
+-
+-import sys
  from setuptools import setup
- 
-+def read(fname):
-+    with open(os.path.join(os.path.dirname(__file__), fname)) as inf:
-+        return "\n" + inf.read().replace("\r\n", "\n")
- 
- def setup_package():
-     needs_sphinx = {'build_sphinx', 'upload_docs'}.intersection(sys.argv)
-     sphinx = ['sphinx'] if needs_sphinx else []
-     setup(
-+        name = "git-deps",
-+        description = "automatically detect dependencies between git commits",
-+        author = "Adam Spiers",
-+        author_email = "g...@adamspiers.org",
-+        license = "GPL-2+",
-+        url = "https://github.com/aspiers/git-deps";,
-+        long_description = read("README.md"),
-+        classifiers = [
-+            "Development Status :: 4 - Beta",
-+            "Environment :: Console",
-+            "Environment :: Web Environment",
-+            "Framework :: Flask",
-+            "Intended Audience :: Developers",
-+            "License :: OSI Approved :: GNU General Public License v2 or 
later (GPLv2+)",
-+            "Natural Language :: English",
-+            "Operating System :: OS Independent",
-+            "Programming Language :: Python",
-+            "Topic :: Software Development :: Version Control",
-+            "Topic :: Utilities"
-+        ],
-+        scripts = ["bin/git-fixup"],
-+        packages = ["git_deps", "git_deps/listener"],
-+        # data_files = "share/git_deps = share/gitfile-handler.desktop",
-         setup_requires=[
-             'six',
--            'pyscaffold>=2.5.10,<2.6a0',
--            'setuptools-markdown',
-         ] + sphinx,
--        long_description_markdown_filename='README.md',
+
+
+-def setup_package():
+-    needs_sphinx = {'build_sphinx', 'upload_docs'}.intersection(sys.argv)
+-    sphinx = ['sphinx'] if needs_sphinx else []
+-    setup(
+-        setup_requires=[
+-            'pyscaffold',
+-        ] + sphinx,
+-        long_description='README.md',
+-        long_description_content_type="text/markdown",
 -        use_pyscaffold=True
-+        entry_points = {
-+            "console_scripts" : [
-+                "git-deps = git_deps.cli:run",
-+                "gitfile-handler = git_deps.handler:run"
-+            ]
-+        }
-     )
- 
- 
---- a/docs/conf.py
-+++ b/docs/conf.py
-@@ -45,7 +45,7 @@ if on_rtd:
- # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
- extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 
'sphinx.ext.todo',
-               'sphinx.ext.autosummary', 'sphinx.ext.viewcode', 
'sphinx.ext.coverage',
--              'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 
'sphinx.ext.pngmath',
-+              'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 
'sphinx.ext.imgmath',
-               'sphinx.ext.napoleon']
- 
- # Add any paths that contain templates here, relative to this directory.
+-    )
+-
+-
+-if __name__ == "__main__":
+-    setup_package()
++setup()
+--- a/tests/create-repo.sh
++++ b/tests/create-repo.sh
+@@ -10,7 +10,6 @@ two
+ three
+ four
+ five
+-six
+ seven
+ eight
+ nine
 

++++++ git-deps-1.0.2+git.1559732444.7c75531.tar.xz -> 
git-deps-1.1.0+git.1696898573.89d51e8.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/.travis.yml 
new/git-deps-1.1.0+git.1696898573.89d51e8/.travis.yml
--- old/git-deps-1.0.2+git.1559732444.7c75531/.travis.yml       2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/.travis.yml       1970-01-01 
01:00:00.000000000 +0100
@@ -1,24 +0,0 @@
-sudo: false
-language: python
-matrix:
-  include:
-  - python: 2.7
-    env: TOX_ENV=flake8
-  - python: 2.7
-    env: TOX_ENV=py27
-  - python: 3.4
-    env: TOX_ENV=py34
-  - python: 3.6
-    env: TOX_ENV=py36
-addons:
-  apt:
-    sources:
-      debian-sid
-    update: true
-    packages:
-      libgit2-24
-      libgit2-dev
-install:
-- pip install tox
-script:
-- tox -e $TOX_ENV
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/AUTHORS.rst 
new/git-deps-1.1.0+git.1696898573.89d51e8/AUTHORS.rst
--- old/git-deps-1.0.2+git.1559732444.7c75531/AUTHORS.rst       2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/AUTHORS.rst       2023-10-10 
02:42:53.000000000 +0200
@@ -2,4 +2,7 @@
 Developers
 ==========
 
-* Adam Spiers <g...@adamspiers.org>
+`git-deps` was written by Adam Spiers <g...@adamspiers.org>.
+
+Contributions from others can be seen in the git history, and at
+https://github.com/aspiers/git-deps/.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/CHANGES.rst 
new/git-deps-1.1.0+git.1696898573.89d51e8/CHANGES.rst
--- old/git-deps-1.0.2+git.1559732444.7c75531/CHANGES.rst       2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/CHANGES.rst       2023-10-10 
02:42:53.000000000 +0200
@@ -2,6 +2,69 @@
 Changelog
 =========
 
+Version 1.1.0
+=============
+
+- Improve support for Python 3.
+
+- ALGORITHM CHANGE: only diff tree with first parent.
+
+   Running ``git deps`` on ``FOO^!`` is effectively answering the
+   question "which commits would I need in order to be able to cleanly
+   cherry-pick commit ``FOO``?"  Drilling down further, that could be
+   rephrased more precisely as "which commits would I need in my
+   current branch in order to be able to cleanly apply the diff which
+   commit ``FOO`` applies to its parent?"
+
+   However, in the case where ``FOO`` is a merge commit with multiple
+   parents, typically the first parent ``P1`` is the parent which is
+   contained by the merge's target branch ``B1``.  That means that the
+   merge commit ``FOO`` has the effect of applying the diff between
+   ``P1``'s tree and the ``FOO``'s tree to ``P1``.  This could be
+   expressed as::
+
+     tree(P1) + diff(tree(P1), tree(FOO)) == tree(FOO)
+
+   Therefore the question ``git deps`` needs to answer when operating
+   on a commit with multiple parents is "which commits would I need in
+   my current branch in order to be able to cleanly apply
+   ``diff(tree(P1), tree(FOO))`` to it?"
+
+   However, the current algorithm runs the blame analysis not only on
+   ``diff(tree(P1), tree(FOO))``, but on ``diff(tree(Px), tree(FOO))``
+   for *every* parent.  This is problematic, because for instance if
+   the target branch contains commits which are not on ``P2``'s
+   branch, then::
+
+     diff(tree(P2), tree(FOO))
+
+   will regress any changes provided by those commits.  This will
+   introduce extra dependencies which incorrectly answer the above
+   question we are trying to answer.
+
+   Therefore change the algorithm to only diff against the first parent.
+
+   This is very similar in nature to the ``-m`` option of ``git cherry-pick``:
+
+   
https://stackoverflow.com/questions/12626754/git-cherry-pick-syntax-and-merge-branches/12628579#12628579
+
+   In the future it may be desirable to add an analogous ``-m`` option
+   to ``git deps``.
+
+- Add ``git-fixup``.
+
+- Allow clean interruption via ``Control+C``.
+
+- Fix output buffering issue.
+
+- Upgrade jQuery.
+
+- Improve debugging output.
+
+- Refactor internals.
+
+- Improve documentation.
+
 Version 1.0.2
 =============
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/INSTALL.md 
new/git-deps-1.1.0+git.1696898573.89d51e8/INSTALL.md
--- old/git-deps-1.0.2+git.1559732444.7c75531/INSTALL.md        2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/INSTALL.md        2023-10-10 
02:42:53.000000000 +0200
@@ -11,6 +11,32 @@
 certain combinations of libgit2 and pygit2 will work
 together](http://www.pygit2.org/install.html#version-numbers).
 
+Also, Python < 3.7 is no longer supported for `git-deps` (since pygit2
+requires 3.7 or higher).
+
+## Option 0 (easiest): let `pip` take care of everything
+
+As mentioned in [`pygit2`'s installation
+instructions](https://www.pygit2.org/install.html), `pip` 19.0 and
+later can install binary wheels of `pygit2` which include `libgit2`.
+This makes installation considerably easier, and should be as simple
+as:
+
+    sudo pip3 install git-deps
+
+or just for the current user:
+
+    pip3 install --user git-deps
+
+For a per-user install, you will probably have to also ensure that you
+have `~/.local/bin` on your path.  See [the `pip`
+documentation](https://pip.pypa.io/en/stable/) if you are unsure how
+this works.
+
+Also note that it may be `pip` rather than `pip3` on your system, but
+if so run `pip --version` to make sure that you aren't getting a
+Python 2.x environment by mistake.
+
 ## Option 1: Install pygit2 and libgit2 from OS packages, and `git-deps` as a 
Python module
 
 ### Install OS packages
@@ -18,13 +44,16 @@
 if you are using Linux, there is a good chance that your distribution
 already offers packages for both pygit2 and libgit2, in which case
 installing pygit2 from packages should also automatically install
-libgit2.  For example, on openSUSE, just do:
+libgit2.  For example, on openSUSE, just do something like:
+
+    sudo zypper install python38-pygit2
 
-    sudo zypper install python-pygit2
+Note that this assumes Python 3.8, which is the latest at the time of
+writing.
 
-or on Debian:
+Similarly, on Debian:
 
-    sudo apt-get install python-pygit2
+    sudo apt-get install python3-pygit2
 
 pygit2's website also has installation instructions for
 [Windows](http://www.pygit2.org/install.html#installing-on-windows)
@@ -35,11 +64,14 @@
 Finally, install `git-deps` via `pip`, for example system-wide on
 Linux via:
 
-    sudo pip install git-deps
+    sudo pip3 install git-deps
 
 or just for the current user:
 
-    pip install --user git-deps
+    pip3 install --user git-deps
+
+(See the caveats in option 0 above about `pip` vs. `pip3` and per-user
+installs.)
 
 ## Option 2: Install libgit2 from OS packages, and `git-deps` / pygit2 as 
Python modules
 
@@ -69,6 +101,10 @@
 
     python setup.py install
 
+or if you want to hack on git-deps:
+
+    pip install -e .
+
 ## Option 4: Installation via Docker
 
 Rather than following the above manual steps, you can try
@@ -95,25 +131,28 @@
 experts who have suggestions about other ways to install are [warmly
 encouraged to submit them](CONTRIBUTING.md).
 
-*   Install `browserify`.  For example (at least on Linux) if you want
-    it to be accessible directly from the command-line then you can
-    use the `-g` option of `npm` by running this as `root`:
-
-         npm install -g browserify
-
 *   To install the required Javascript libraries, you will need
     [`npm`](https://www.npmjs.com/) installed, and then type:
 
         cd git_deps/html
         npm install
-        browserify -t coffeeify -d js/git-deps-graph.coffee -o js/bundle.js
+        node_modules/.bin/browserify -t coffeeify -d js/git-deps-graph.coffee 
-o js/bundle.js
 
     (If you are developing `git-deps` then replace `browserify` with
     `watchify -v` in order to continually regenerate `bundle.js`
     whenever any of the input files change.)
 
-*   You will need the [Flask](http://flask.pocoo.org/) Python
-    module installed.
+*   Optionally install `browserify` globally so that it's on your
+    `$PATH` and therefore executable directly rather than having to
+    specify the `node_modules/.bin` prefix.  For example (at least on
+    Linux) you can use the `-g` option of `npm` by running this as
+    `root`:
+
+         npm install -g browserify
+
+*   You will need the [Flask](http://flask.pocoo.org/) Python module
+    installed, but that should have already been taken care of by the
+    base installation described above (e.g. via `pip`).
 
 Now you should be able to run `git deps --serve` and point your
 browser at the URL it outputs.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/docs/_static/.gitignore 
new/git-deps-1.1.0+git.1696898573.89d51e8/docs/_static/.gitignore
--- old/git-deps-1.0.2+git.1559732444.7c75531/docs/_static/.gitignore   
1970-01-01 01:00:00.000000000 +0100
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/docs/_static/.gitignore   
2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1 @@
+# Empty directory
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/docs/conf.py 
new/git-deps-1.1.0+git.1696898573.89d51e8/docs/conf.py
--- old/git-deps-1.0.2+git.1559732444.7c75531/docs/conf.py      2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/docs/conf.py      2023-10-10 
02:42:53.000000000 +0200
@@ -45,7 +45,7 @@
 # coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
 extensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 
'sphinx.ext.todo',
               'sphinx.ext.autosummary', 'sphinx.ext.viewcode', 
'sphinx.ext.coverage',
-              'sphinx.ext.doctest', 'sphinx.ext.ifconfig', 
'sphinx.ext.pngmath',
+              'sphinx.ext.doctest', 'sphinx.ext.ifconfig',
               'sphinx.ext.napoleon']
 
 # Add any paths that contain templates here, relative to this directory.
@@ -239,7 +239,7 @@
 # -- External mapping 
------------------------------------------------------------
 python_version = '.'.join(map(str, sys.version_info[0:2]))
 intersphinx_mapping = {
-    'sphinx': ('http://sphinx.pocoo.org', None),
+    'sphinx': ('https://www.sphinx-doc.org/en/master', None),
     'python': ('http://docs.python.org/' + python_version, None),
     'matplotlib': ('http://matplotlib.sourceforge.net', None),
     'numpy': ('http://docs.scipy.org/doc/numpy', None),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/docs/index.rst 
new/git-deps-1.1.0+git.1696898573.89d51e8/docs/index.rst
--- old/git-deps-1.0.2+git.1559732444.7c75531/docs/index.rst    2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/docs/index.rst    2023-10-10 
02:42:53.000000000 +0200
@@ -15,10 +15,11 @@
 .. toctree::
    :maxdepth: 2
 
-   License <license>
-   Authors <authors>
    Changelog <changes>
    Module Reference <api/modules>
+   Maintainer's Guide <maintainer-guide>
+   Authors <authors>
+   License <license>
 
 
 Indices and tables
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/docs/maintainer-guide.rst 
new/git-deps-1.1.0+git.1696898573.89d51e8/docs/maintainer-guide.rst
--- old/git-deps-1.0.2+git.1559732444.7c75531/docs/maintainer-guide.rst 
2019-06-05 13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/docs/maintainer-guide.rst 
2023-10-10 02:42:53.000000000 +0200
@@ -27,14 +27,17 @@
 
 - Run ``tox`` to check everything is OK.
 
-- Decide a new version.  Release candidates should take the form
-  ``1.2.3rc4``.
+- Decide a new version, e.g.::
+
+    version=1.1.0
+
+  Release candidates should take the form ``1.2.3rc4``.
 
 - ``git tag -s $version``
 
 - ``tox -e sdist``
 
-- ``twine dist/git-deps-$version.tar.gz``
+- ``twine upload .tox/dist/git-deps-$version.zip``
 
 - Check the new version appears at `<https://pypi.org/project/git-deps/>`_.
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/blame.py 
new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/blame.py
--- old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/blame.py 1970-01-01 
01:00:00.000000000 +0100
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/blame.py 2023-10-10 
02:42:53.000000000 +0200
@@ -0,0 +1,61 @@
+import subprocess
+import re
+from dataclasses import dataclass
+
+# The following classes are introduced to imitate their counterparts in pygit2,
+# so that the output of 'blame_via_subprocess' can be swapped with pygit2's own
+# blame output.
+
+@dataclass
+class GitRef:
+    """
+    A reference to a commit
+    """
+    hex: str
+
+@dataclass
+class BlameHunk:
+    """
+    A chunk of a blame output which has the same commit information
+    for a consecutive set of lines
+    """
+    orig_commit_id: GitRef
+    orig_start_line_number: int
+    final_start_line_number: int
+    lines_in_hunk: int = 1
+
+
+def blame_via_subprocess(path, commit, start_line, num_lines):
+    """
+    Generate a list of blame hunks by calling 'git blame' as a separate 
process.
+    This is a workaround for the slowness of pygit2's own blame algorithm.
+    See https://github.com/aspiers/git-deps/issues/1
+    """
+    cmd = [
+        'git', 'blame',
+        '--porcelain',
+        '-L', "%d,+%d" % (start_line, num_lines),
+        commit, '--', path
+    ]
+    output = subprocess.check_output(cmd, universal_newlines=True)
+
+    current_hunk = None
+    for line in output.split('\n'):
+        m = re.match(r'^([0-9a-f]{40}) (\d+) (\d+) (\d+)$', line)
+
+        if m: # starting a new hunk
+            if current_hunk:
+                yield current_hunk
+            dependency_sha1, orig_line_num, line_num, length = m.group(1, 2, 
3, 4)
+            orig_line_num = int(orig_line_num)
+            line_num = int(line_num)
+            length = int(length)
+            current_hunk = BlameHunk(
+                orig_commit_id=GitRef(dependency_sha1),
+                orig_start_line_number = orig_line_num,
+                final_start_line_number = line_num,
+                lines_in_hunk = length
+            )
+
+    if current_hunk:
+        yield current_hunk
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/cli.py 
new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/cli.py
--- old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/cli.py   2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/cli.py   2023-10-10 
02:42:53.000000000 +0200
@@ -75,6 +75,8 @@
                         '[%(default)s]')
     parser.add_argument('-d', '--debug', dest='debug', action='store_true',
                         help='Show debugging')
+    parser.add_argument('--pygit2-blame', dest='pygit2_blame', 
action='store_true',
+                        help="Use pygit2's blame algorithm (slower than 
git's)")
 
     options, args = parser.parse_known_args()
 
@@ -122,7 +124,7 @@
             try:
                 detector.find_dependencies(rev)
             except KeyboardInterrupt:
-                pass
+                break
 
     if options.json:
         print(json.dumps(listener.json(), sort_keys=True, indent=4))
@@ -135,7 +137,7 @@
     if options.serve:
         serve(options)
     else:
-        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
+        sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
         try:
             cli(options, args)
         except InvalidCommitish as e:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/detector.py 
new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/detector.py
--- old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/detector.py      
2019-06-05 13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/detector.py      
2023-10-10 02:42:53.000000000 +0200
@@ -7,6 +7,7 @@
 from git_deps.gitutils import GitUtils
 from git_deps.listener.base import DependencyListener
 from git_deps.errors import InvalidCommitish
+from git_deps.blame import blame_via_subprocess
 
 
 class DependencyDetector(object):
@@ -109,21 +110,23 @@
             dependent_sha1 = dependent.hex
             del self.todo_d[dependent_sha1]
             self.logger.info("  Processing %s from TODO list" %
-                              dependent_sha1[:8])
+                             dependent_sha1[:8])
 
             if dependent_sha1 in self.done_d:
                 self.logger.info("  %s already done previously" %
-                                  dependent_sha1)
+                                 dependent_sha1)
                 continue
 
             self.notify_listeners('new_commit', dependent)
 
-            parent = dependent.parents[0]
-            self.find_dependencies_with_parent(dependent, parent)
+            if dependent.parents: # the root commit does not have parents
+                parent = dependent.parents[0]
+                self.find_dependencies_with_parent(dependent, parent)
+
             self.done.append(dependent_sha1)
             self.done_d[dependent_sha1] = True
             self.logger.info("  Found all dependencies for %s" %
-                              dependent_sha1[:8])
+                             dependent_sha1[:8])
             # A commit won't have any dependencies if it only added new files
             dependencies = self.dependencies.get(dependent_sha1, {})
             self.notify_listeners('dependent_done', dependent, dependencies)
@@ -137,7 +140,7 @@
         merge commits which have multiple parents.
         """
         self.logger.info("    Finding dependencies of %s via parent %s" %
-                          (dependent.hex[:8], parent.hex[:8]))
+                         (dependent.hex[:8], parent.hex[:8]))
         diff = self.repo.diff(parent, dependent,
                               context_lines=self.options.context_lines)
         for patch in diff:
@@ -156,7 +159,7 @@
         line_range_before = "-%d,%d" % (hunk.old_start, hunk.old_lines)
         line_range_after = "+%d,%d" % (hunk.new_start, hunk.new_lines)
         self.logger.info("        Blaming hunk %s @ %s (listed below)" %
-                          (line_range_before, parent.hex[:8]))
+                         (line_range_before, parent.hex[:8]))
 
         if not self.tree_lookup(path, parent):
             # This is probably because dependent added a new directory
@@ -170,24 +173,26 @@
 
         line_to_culprit = {}
 
-        for line in blame.split('\n'):
-            self.process_hunk_line(dependent, dependent_sha1, parent,
-                                   path, line, line_to_culprit)
+        for blame_hunk in blame:
+            self.process_blame_hunk(dependent, dependent_sha1, parent,
+                                   path, blame_hunk, line_to_culprit)
 
         self.debug_hunk(line_range_before, line_range_after, hunk,
                         line_to_culprit)
 
-    def process_hunk_line(self, dependent, dependent_sha1, parent,
-                          path, line, line_to_culprit):
-        self.logger.debug("          ! " + line.rstrip())
-        m = re.match('^([0-9a-f]{40}) (\d+) (\d+)( \d+)?$', line)
-        if not m:
-            return
+    def process_blame_hunk(self, dependent, dependent_sha1, parent,
+                          path, blame_hunk, line_to_culprit):
+
+        orig_line_num = blame_hunk.orig_start_line_number
+        line_num = blame_hunk.final_start_line_number
+        dependency_sha1 = blame_hunk.orig_commit_id.hex
+        line_representation = f"{dependency_sha1} {orig_line_num} {line_num}"
+
+        self.logger.debug(f"          ! {line_representation}")
 
-        dependency_sha1, orig_line_num, line_num = m.group(1, 2, 3)
-        line_num = int(line_num)
         dependency = self.get_commit(dependency_sha1)
-        line_to_culprit[line_num] = dependency.hex
+        for i in range(blame_hunk.lines_in_hunk):
+            line_to_culprit[line_num + i] = dependency.hex
 
         if self.is_excluded(dependency):
             self.logger.debug(
@@ -204,7 +209,7 @@
         self.record_dependency_source(parent,
                                       dependent, dependent_sha1,
                                       dependency, dependency_sha1,
-                                      path, line_num, line)
+                                      path, line_num, line_representation)
 
     def debug_hunk(self, line_range_before, line_range_after, hunk,
                    line_to_culprit):
@@ -227,18 +232,21 @@
     def register_new_dependent(self, dependent, dependent_sha1):
         if dependent_sha1 not in self.dependencies:
             self.logger.info("          New dependent: %s" %
-                              GitUtils.commit_summary(dependent))
+                             GitUtils.commit_summary(dependent))
             self.dependencies[dependent_sha1] = {}
             self.notify_listeners("new_dependent", dependent)
 
     def run_blame(self, hunk, parent, path):
-        cmd = [
-            'git', 'blame',
-            '--porcelain',
-            '-L', "%d,+%d" % (hunk.old_start, hunk.old_lines),
-            parent.hex, '--', path
-        ]
-        return subprocess.check_output(cmd, universal_newlines=True)
+        if self.options.pygit2_blame:
+            return self.repo.blame(path,
+                        newest_commit=parent.hex,
+                        min_line=hunk.old_start,
+                        max_line=hunk.old_start + hunk.old_lines - 1)
+        else:
+            return blame_via_subprocess(path,
+                        parent.hex,
+                        hunk.old_start,
+                        hunk.old_lines)
 
     def is_excluded(self, commit):
         if self.options.exclude_commits is not None:
@@ -247,7 +255,7 @@
                     return True
         return False
 
-    def process_new_dependency(self,dependent, dependent_sha1,
+    def process_new_dependency(self, dependent, dependent_sha1,
                                dependency, dependency_sha1,
                                path, line_num):
         if not self.seen_commit(dependency):
@@ -279,7 +287,7 @@
                 self.todo.append(dependency)
                 self.todo_d[dependency.hex] = True
                 self.logger.info("  + Added %s to TODO" %
-                                  dependency.hex[:8])
+                                 dependency.hex[:8])
 
     def record_dependency_source(self, parent,
                                  dependent, dependent_sha1,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/html/.gitignore 
new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/html/.gitignore
--- old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/html/.gitignore  
1970-01-01 01:00:00.000000000 +0100
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/html/.gitignore  
2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1,2 @@
+node_modules/
+bower_components/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/html/js/.gitignore 
new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/html/js/.gitignore
--- old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/html/js/.gitignore       
1970-01-01 01:00:00.000000000 +0100
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/html/js/.gitignore       
2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1 @@
+bundle.js
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/html/package.json 
new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/html/package.json
--- old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/html/package.json        
2019-06-05 13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/html/package.json        
2023-10-10 02:42:53.000000000 +0200
@@ -30,7 +30,7 @@
         "d3": "~3.5.3",
         "d3-tip": "~0.6.6",
         "dagre": "^0.8.2",
-        "jquery": "~3.0.0",
+        "jquery": "~3.5.0",
         "noty": "~v2.4.1",
         "webcola": "aspiers/WebCola#git-deps-master"
     },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/server.py 
new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/server.py
--- old/git-deps-1.0.2+git.1559732444.7c75531/git_deps/server.py        
2019-06-05 13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/git_deps/server.py        
2023-10-10 02:42:53.000000000 +0200
@@ -1,5 +1,6 @@
 import os
 import subprocess
+import sys
 
 from git_deps.gitutils import GitUtils
 from git_deps.detector import DependencyDetector
@@ -11,8 +12,9 @@
 def serve(options):
     try:
         import flask
-        from flask import Flask, send_file, safe_join
+        from flask import Flask, send_file
         from flask.json import jsonify
+        from werkzeug.security import safe_join
     except ImportError:
         abort("Cannot find flask module which is required for webserver mode.")
 
@@ -122,5 +124,17 @@
               "insecure!")
         print("!! Arbitrary code can be executed from browser!")
         print()
-    webserver.run(port=options.port, debug=options.debug,
-                  host=options.bindaddr)
+    try:
+        webserver.run(port=options.port, debug=options.debug,
+                      host=options.bindaddr)
+    except OSError as e:
+        print("\n!!! ERROR: Could not start server:")
+        print("!!!")
+        print("!!!   " + str(e))
+        print("!!!")
+        if e.strerror == "Address already in use":
+            print("!!! Do you already have a git deps server running?")
+            print("!!! If so, stop it first and try again.")
+            print("!!!")
+        print("!!! Aborting.")
+        sys.exit(1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/setup.cfg 
new/git-deps-1.1.0+git.1696898573.89d51e8/setup.cfg
--- old/git-deps-1.0.2+git.1559732444.7c75531/setup.cfg 2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/setup.cfg 2023-10-10 
02:42:53.000000000 +0200
@@ -2,10 +2,10 @@
 name = git-deps
 summary = automatically detect dependencies between git commits
 author = Adam Spiers
-author-email = g...@adamspiers.org
+author_email = g...@adamspiers.org
 license = GPL-2+
-home-page = https://github.com/aspiers/git-deps
-description-file = README.md
+home_page = https://github.com/aspiers/git-deps
+description_file = README.md
 classifier =
     Development Status :: 4 - Beta
     Environment :: Console
@@ -27,11 +27,17 @@
 [files]
 scripts =
     bin/git-fixup
-packages =
-    git_deps
 data_files =
     share/git_deps = share/gitfile-handler.desktop
 
+[options]
+packages =
+    git_deps
+
+[options.entry_points]
+console_scripts =
+    git-deps = git_deps.cli:run
+
 [test]
 # py.test options when running `python setup.py test`
 addopts = tests
@@ -64,7 +70,7 @@
 # autodoc_index_modules = True
 # autodoc_exclude_modules = ...
 # Convert warnings to errors
-# warnerrors = True
+warnerrors = True
 
 [devpi:upload]
 # Options for the devpi: PyPI server and packaging tool
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/setup.py 
new/git-deps-1.1.0+git.1696898573.89d51e8/setup.py
--- old/git-deps-1.0.2+git.1559732444.7c75531/setup.py  2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/setup.py  2023-10-10 
02:42:53.000000000 +0200
@@ -17,11 +17,10 @@
     sphinx = ['sphinx'] if needs_sphinx else []
     setup(
         setup_requires=[
-            'six',
-            'pyscaffold>=2.5.10,<2.6a0',
-            'setuptools-markdown',
+            'pyscaffold',
         ] + sphinx,
-        long_description_markdown_filename='README.md',
+        long_description='README.md',
+        long_description_content_type="text/markdown",
         use_pyscaffold=True
     )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/.gitignore 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/.gitignore
--- old/git-deps-1.0.2+git.1559732444.7c75531/tests/.gitignore  1970-01-01 
01:00:00.000000000 +0100
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/tests/.gitignore  2023-10-10 
02:42:53.000000000 +0200
@@ -0,0 +1 @@
+test-repo/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/expected_outputs/deps_1ba7ad5 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/expected_outputs/deps_1ba7ad5
--- 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/expected_outputs/deps_1ba7ad5   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/expected_outputs/deps_1ba7ad5   
    2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1,3 @@
+2bd9ea0f03a644cc3f5e7824d9ad0979ccdf94dc
+2c9d23b0291157eb1096384ff76e0122747b9bdf
+c15f0364bf0364b8123b370b78b6d6ac8bf6f779
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/expected_outputs/deps_4f27a1e 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/expected_outputs/deps_4f27a1e
--- 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/expected_outputs/deps_4f27a1e   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/expected_outputs/deps_4f27a1e   
    2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1,7 @@
+3374b8419a45d91d3c0631be11c8cf893b272217
+3a1dd42fd6114a634ba7cf037ce61e2aee76db73
+5ec5ccbdff508014c61ae9d18f3366a15c0f2689
+80c247fd21a1e7f476d1c8ba289498e216eff3dc
+b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+b1967573e81a8100a4cc778936de0ba0a8a8f5cb
+f7bf058439fd7499aad7a10418a9f516e6949fbc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/expected_outputs/recursive_deps_4f27a1e
 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/expected_outputs/recursive_deps_4f27a1e
--- 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/expected_outputs/recursive_deps_4f27a1e
     1970-01-01 01:00:00.000000000 +0100
+++ 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/expected_outputs/recursive_deps_4f27a1e
     2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1,29 @@
+2a05400e232e14f0d4c1cbfb548a0871ea57bd44 
3374b8419a45d91d3c0631be11c8cf893b272217
+2a05400e232e14f0d4c1cbfb548a0871ea57bd44 
b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+2ebcb2b6081e32e9a463519525bd432287b24520 
3a1dd42fd6114a634ba7cf037ce61e2aee76db73
+2ebcb2b6081e32e9a463519525bd432287b24520 
acc24a404d82061bbc6db5afb146d83bf131830b
+3374b8419a45d91d3c0631be11c8cf893b272217 
3a1dd42fd6114a634ba7cf037ce61e2aee76db73
+3374b8419a45d91d3c0631be11c8cf893b272217 
b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+3374b8419a45d91d3c0631be11c8cf893b272217 
b1967573e81a8100a4cc778936de0ba0a8a8f5cb
+3a1dd42fd6114a634ba7cf037ce61e2aee76db73 
b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+3a1dd42fd6114a634ba7cf037ce61e2aee76db73 
b1967573e81a8100a4cc778936de0ba0a8a8f5cb
+4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 
3374b8419a45d91d3c0631be11c8cf893b272217
+4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 
3a1dd42fd6114a634ba7cf037ce61e2aee76db73
+4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 
5ec5ccbdff508014c61ae9d18f3366a15c0f2689
+4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 
80c247fd21a1e7f476d1c8ba289498e216eff3dc
+4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 
b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 
b1967573e81a8100a4cc778936de0ba0a8a8f5cb
+4f27a1ee2b5fd63a58311a20e2aed0a24eda8da2 
f7bf058439fd7499aad7a10418a9f516e6949fbc
+5ec5ccbdff508014c61ae9d18f3366a15c0f2689 
3374b8419a45d91d3c0631be11c8cf893b272217
+5ec5ccbdff508014c61ae9d18f3366a15c0f2689 
b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+80c247fd21a1e7f476d1c8ba289498e216eff3dc 
2ebcb2b6081e32e9a463519525bd432287b24520
+80c247fd21a1e7f476d1c8ba289498e216eff3dc 
3a1dd42fd6114a634ba7cf037ce61e2aee76db73
+80c247fd21a1e7f476d1c8ba289498e216eff3dc 
acc24a404d82061bbc6db5afb146d83bf131830b
+80c247fd21a1e7f476d1c8ba289498e216eff3dc 
b1967573e81a8100a4cc778936de0ba0a8a8f5cb
+acc24a404d82061bbc6db5afb146d83bf131830b 
3a1dd42fd6114a634ba7cf037ce61e2aee76db73
+acc24a404d82061bbc6db5afb146d83bf131830b 
b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5 
b1967573e81a8100a4cc778936de0ba0a8a8f5cb
+f7bf058439fd7499aad7a10418a9f516e6949fbc 
2a05400e232e14f0d4c1cbfb548a0871ea57bd44
+f7bf058439fd7499aad7a10418a9f516e6949fbc 
80c247fd21a1e7f476d1c8ba289498e216eff3dc
+f7bf058439fd7499aad7a10418a9f516e6949fbc 
b144bfd5feb327ef7ce0c26bbfb6f4da573abfe5
+f7bf058439fd7499aad7a10418a9f516e6949fbc 
b1967573e81a8100a4cc778936de0ba0a8a8f5cb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/self_test.sh 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/self_test.sh
--- old/git-deps-1.0.2+git.1559732444.7c75531/tests/self_test.sh        
1970-01-01 01:00:00.000000000 +0100
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/tests/self_test.sh        
2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+set -eo pipefail
+
+# Collection of tests consisting in running `git-deps` on its own repository.
+# The expected outputs of various commands are stored in the 
`expected_outputs` subdirectory.
+
+# Because git-deps can only be run from the repository's root, this script 
should be run at
+# the root of a clone of git-deps. The clone should not be shallow, so that 
all refs can be accessed.
+
+echo "Running test suite"
+
+echo "* Dependencies of 4f27a1e, a regular commit"
+git-deps 4f27a1e^! | sort | diff tests/expected_outputs/deps_4f27a1e -
+
+echo "* Same, but via pygit2's blame algorithm"
+git-deps --pygit2-blame 4f27a1e^! | sort | diff 
tests/expected_outputs/deps_4f27a1e -
+
+echo "* Dependencies of 1ba7ad5, a merge commit"
+git-deps 1ba7ad5^! | sort | diff tests/expected_outputs/deps_1ba7ad5 -
+
+echo "* Same, but via pygit2's blame algorithm"
+git-deps --pygit2-blame 1ba7ad5^! | sort | diff 
tests/expected_outputs/deps_1ba7ad5 -
+
+echo "* Dependencies of the root commit"
+git-deps b196757^! | sort | diff tests/expected_outputs/deps_b196757 -
+
+echo "* Same, but via pygit2's blame algorithm"
+git-deps --pygit2-blame b196757^! | sort | diff 
tests/expected_outputs/deps_b196757 -
+
+echo "* Recursive dependencies of a4f27a1e, a regular commit"
+git-deps -r 4f27a1e^! | sort | diff 
tests/expected_outputs/recursive_deps_4f27a1e -
+
+echo "All tests passed!"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/git-deps-1.0.2+git.1559732444.7c75531/tests/test_blame.py 
new/git-deps-1.1.0+git.1696898573.89d51e8/tests/test_blame.py
--- old/git-deps-1.0.2+git.1559732444.7c75531/tests/test_blame.py       
1970-01-01 01:00:00.000000000 +0100
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/tests/test_blame.py       
2023-10-10 02:42:53.000000000 +0200
@@ -0,0 +1,24 @@
+
+from git_deps.blame import blame_via_subprocess, BlameHunk, GitRef
+
+def test_blame_via_subprocess():
+    hunks = list(blame_via_subprocess(
+        'INSTALL.md',
+        '04f5c095d4eccf5808db6dbf90c31a535f7f371c',
+        12, 4))
+
+    expected_hunks = [
+        BlameHunk(
+            GitRef('6e23a48f888a355ad7e101c797ce1b66c4b7b86a'),
+            orig_start_line_number=12,
+            final_start_line_number=12,
+            lines_in_hunk=2),
+        BlameHunk(
+            GitRef('2c9d23b0291157eb1096384ff76e0122747b9bdf'),
+            orig_start_line_number=10,
+            final_start_line_number=14,
+            lines_in_hunk=2)
+    ]
+
+    assert hunks == expected_hunks
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/git-deps-1.0.2+git.1559732444.7c75531/tox.ini 
new/git-deps-1.1.0+git.1696898573.89d51e8/tox.ini
--- old/git-deps-1.0.2+git.1559732444.7c75531/tox.ini   2019-06-05 
13:00:44.000000000 +0200
+++ new/git-deps-1.1.0+git.1696898573.89d51e8/tox.ini   2023-10-10 
02:42:53.000000000 +0200
@@ -3,7 +3,7 @@
 
 [tox]
 minversion = 1.8
-envlist = py27,py34,py36,flake8
+envlist = py37,py38,flake8
 skip_missing_interpreters = True
 
 [testenv]

++++++ no-pkg-resources.patch ++++++
---
 git_deps/__init__.py |    7 +------
 setup.cfg            |    2 +-
 2 files changed, 2 insertions(+), 7 deletions(-)

--- a/git_deps/__init__.py
+++ b/git_deps/__init__.py
@@ -1,6 +1 @@
-import pkg_resources
-
-try:
-    __version__ = pkg_resources.get_distribution(__name__).version
-except pkg_resources.DistributionNotFound:
-    __version__ = 'unknown'
+__version__ = '1.1.0'
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = git-deps
-version = 1.1.0
+version = attr: git_deps.__version__
 summary = automatically detect dependencies between git commits
 author = Adam Spiers
 author_email = g...@adamspiers.org

++++++ pygit2-1.15.0.patch ++++++
>From a1c990c8419ef4d03de86ae7ef7ea94b32fce1c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Koutn=C3=BD?= <mkou...@suse.com>
Date: Wed, 3 Jul 2024 19:25:40 +0200
Subject: [PATCH 1/3] pygit2 update: Use id when indexing into repo objects

---
 git_deps/detector.py      |   36 ++++++++++++++++++------------------
 git_deps/gitutils.py      |    4 ++--
 git_deps/listener/cli.py  |    6 +++---
 git_deps/listener/json.py |    8 ++++----
 git_deps/server.py        |    2 +-
 5 files changed, 28 insertions(+), 28 deletions(-)

--- a/git_deps/detector.py
+++ b/git_deps/detector.py
@@ -95,19 +95,19 @@ class DependencyDetector(object):
             abort(e.message())

         self.todo.append(dependent)
-        self.todo_d[dependent.hex] = True
+        self.todo_d[str(dependent.id)] = True

         first_time = True

         while self.todo:
-            sha1s = [commit.hex[:8] for commit in self.todo]
+            sha1s = [str(commit.id)[:8] for commit in self.todo]
             if first_time:
                 self.logger.info("Initial TODO list: %s" % " ".join(sha1s))
                 first_time = False
             else:
                 self.logger.info("  TODO list now: %s" % " ".join(sha1s))
             dependent = self.todo.pop(0)
-            dependent_sha1 = dependent.hex
+            dependent_sha1 = str(dependent.id)
             del self.todo_d[dependent_sha1]
             self.logger.info("  Processing %s from TODO list" %
                              dependent_sha1[:8])
@@ -140,7 +140,7 @@ class DependencyDetector(object):
         merge commits which have multiple parents.
         """
         self.logger.info("    Finding dependencies of %s via parent %s" %
-                         (dependent.hex[:8], parent.hex[:8]))
+                         (str(dependent.id)[:8], str(parent.id)[:8]))
         diff = self.repo.diff(parent, dependent,
                               context_lines=self.options.context_lines)
         for patch in diff:
@@ -159,7 +159,7 @@ class DependencyDetector(object):
         line_range_before = "-%d,%d" % (hunk.old_start, hunk.old_lines)
         line_range_after = "+%d,%d" % (hunk.new_start, hunk.new_lines)
         self.logger.info("        Blaming hunk %s @ %s (listed below)" %
-                         (line_range_before, parent.hex[:8]))
+                         (line_range_before, str(parent.id)[:8]))

         if not self.tree_lookup(path, parent):
             # This is probably because dependent added a new directory
@@ -168,7 +168,7 @@ class DependencyDetector(object):

         blame = self.run_blame(hunk, parent, path)

-        dependent_sha1 = dependent.hex
+        dependent_sha1 = str(dependent.id)
         self.register_new_dependent(dependent, dependent_sha1)

         line_to_culprit = {}
@@ -185,14 +185,14 @@ class DependencyDetector(object):

         orig_line_num = blame_hunk.orig_start_line_number
         line_num = blame_hunk.final_start_line_number
-        dependency_sha1 = blame_hunk.orig_commit_id.hex
+        dependency_sha1 = str(blame_hunk.orig_commit_id.hex)
         line_representation = f"{dependency_sha1} {orig_line_num} {line_num}"

         self.logger.debug(f"          ! {line_representation}")

         dependency = self.get_commit(dependency_sha1)
         for i in range(blame_hunk.lines_in_hunk):
-            line_to_culprit[line_num + i] = dependency.hex
+            line_to_culprit[line_num + i] = str(dependency.id)

         if self.is_excluded(dependency):
             self.logger.debug(
@@ -239,12 +239,12 @@ class DependencyDetector(object):
     def run_blame(self, hunk, parent, path):
         if self.options.pygit2_blame:
             return self.repo.blame(path,
-                        newest_commit=parent.hex,
+                        newest_commit=str(parent.id),
                         min_line=hunk.old_start,
                         max_line=hunk.old_start + hunk.old_lines - 1)
         else:
             return blame_via_subprocess(path,
-                        parent.hex,
+                        str(parent.id),
                         hunk.old_start,
                         hunk.old_lines)

@@ -285,9 +285,9 @@ class DependencyDetector(object):
         if dependency_sha1 not in self.dependencies:
             if self.options.recurse:
                 self.todo.append(dependency)
-                self.todo_d[dependency.hex] = True
+                self.todo_d[str(dependency.id)] = True
                 self.logger.info("  + Added %s to TODO" %
-                                 dependency.hex[:8])
+                                 str(dependency.id)[:8])

     def record_dependency_source(self, parent,
                                  dependent, dependent_sha1,
@@ -304,7 +304,7 @@ class DependencyDetector(object):
             abort("line %d already found when blaming %s:%s\n"
                   "old:\n  %s\n"
                   "new:\n  %s" %
-                  (line_num, parent.hex[:8], path,
+                  (line_num, str(parent.id)[:8], path,
                    dep_sources[path][line_num], line))

         dep_sources[path][line_num] = line
@@ -314,9 +314,9 @@ class DependencyDetector(object):
                               dependent, dependency, path, line_num)

     def branch_contains(self, commit, branch):
-        sha1 = commit.hex
+        sha1 = str(commit.id)
         branch_commit = self.get_commit(branch)
-        branch_sha1 = branch_commit.hex
+        branch_sha1 = str(branch_commit.id)
         self.logger.debug("          Does %s (%s) contain %s?" %
                           (branch, branch_sha1[:8], sha1[:8]))

@@ -349,7 +349,7 @@ class DependencyDetector(object):
             dirent = segments.pop(0)
             if isinstance(tree_or_blob, pygit2.Tree):
                 if dirent in tree_or_blob:
-                    tree_or_blob = self.repo[tree_or_blob[dirent].oid]
+                    tree_or_blob = self.repo[tree_or_blob[dirent].id]
                     # self.logger.debug("  %s in %s" % (dirent, path))
                     if path:
                         path += '/'
@@ -358,11 +358,11 @@ class DependencyDetector(object):
                     # This is probably because we were called on a
                     # commit whose parent added a new directory.
                     self.logger.debug("        %s not in %s in %s" %
-                                      (dirent, path, commit.hex[:8]))
+                                      (dirent, path, str(commit.id)[:8]))
                     return None
             else:
                 self.logger.debug("        %s not a tree in %s" %
-                                  (tree_or_blob, commit.hex[:8]))
+                                  (tree_or_blob, str(commit.id)[:8]))
                 return None
         return tree_or_blob

--- a/git_deps/gitutils.py
+++ b/git_deps/gitutils.py
@@ -63,7 +63,7 @@ class GitUtils(object):

     @classmethod
     def commit_summary(cls, commit):
-        return "%s %s" % (commit.hex[:8], cls.oneline(commit))
+        return "%s %s" % (str(commit.id)[:8], cls.oneline(commit))

     @classmethod
     def refs_to(cls, sha1, repo):
@@ -74,7 +74,7 @@ class GitUtils(object):
             dref = symref.resolve()
             oid = dref.target
             commit = repo.get(oid)
-            if commit.hex == sha1:
+            if str(commit.id) == sha1:
                 matching.append(symref.shorthand)

         return matching
--- a/git_deps/listener/cli.py
+++ b/git_deps/listener/cli.py
@@ -20,14 +20,14 @@ class CLIDependencyListener(DependencyLi
         self._revs = {}

     def new_commit(self, commit):
-        rev = commit.hex
+        rev = str(commit.id)
         if rev not in self._revs:
             self._revs[rev] = 0
         self._revs[rev] += 1

     def new_dependency(self, dependent, dependency, path, line_num):
-        dependent_sha1 = dependent.hex
-        dependency_sha1 = dependency.hex
+        dependent_sha1 = str(dependent.id)
+        dependency_sha1 = str(dependency.id)

         if self.options.multi:
             if self.options.log:
--- a/git_deps/listener/json.py
+++ b/git_deps/listener/json.py
@@ -31,7 +31,7 @@ class JSONDependencyListener(DependencyL
         """Adds the commit to the commits array if it doesn't already exist,
         and returns the commit's index in the array.
         """
-        sha1 = commit.hex
+        sha1 = str(commit.id)
         if sha1 in self._commits:
             return self._commits[sha1]
         title, separator, body = commit.message.partition("\n")
@@ -62,8 +62,8 @@ class JSONDependencyListener(DependencyL
         self.add_commit(commit)

     def new_dependency(self, parent, child, path, line_num):
-        ph = parent.hex
-        ch = child.hex
+        ph = str(parent.id)
+        ch = str(child.id)

         new_dep = {
             'parent': ph,
@@ -76,7 +76,7 @@ class JSONDependencyListener(DependencyL
         self._json['dependencies'].append(new_dep)

     def dependent_done(self, dependent, dependencies):
-        commit = self.get_commit(dependent.hex)
+        commit = self.get_commit(str(dependent.id))
         commit['explored'] = True

     def json(self):
--- a/git_deps/server.py
+++ b/git_deps/server.py
@@ -105,7 +105,7 @@ def serve(options):
             detector.find_dependencies(rev)

         tip_commit = detector.get_commit(revisions[0])
-        tip_sha1 = tip_commit.hex
+        tip_sha1 = str(tip_commit.id)

         json = listener.json()
         json['query'] = {

Reply via email to