pyDiffTools 0.1.58__tar.gz → 0.1.59__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pydifftools-0.1.58/pyDiffTools.egg-info → pydifftools-0.1.59}/PKG-INFO +12 -2
- {pydifftools-0.1.58 → pydifftools-0.1.59}/README.rst +11 -1
- {pydifftools-0.1.58 → pydifftools-0.1.59/pyDiffTools.egg-info}/PKG-INFO +12 -2
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pyDiffTools.egg-info/SOURCES.txt +2 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/command_line.py +2 -1
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/git_aliases.py +2 -0
- pydifftools-0.1.59/pydifftools/git_reattach.py +145 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pyproject.toml +1 -1
- pydifftools-0.1.59/tests/test_git_reattach.py +186 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/LICENSE.md +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/MANIFEST.in +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/_quarto.yml +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/1a724af72b16f5a9e607e12b1c721645/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/1b28fc9daac9081847e5161b2c546f8a/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/231f64eee282fa225d1104935cf80a24/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/26e56f6b0ff54851a45145157f2f0dc4/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/311fabd7029ffd050d056e2f316eb50f/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/57da2021e5b156ac3adf01398201c723/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/62b24ea7da75011d92b0f8924faa208d/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/7f1b20d69d889514ab5d1cc92e3cb14f/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/86f74c8c54a87ff892d9b15dd714e8f0/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/88893b4234eac2945d9d6cb2e277f186/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/9a40046ada6f582ee34af00fbdbfb417/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/a1bf4d270d0641ff41faf1d7cce3439a/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/a3789f7d9585a781f2a1c60ce95ff10d/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/be46ecba858d39ad5f0c46902ddf1c02/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/d0cbc57a12f2ccce710a5afd04cc05e7/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/d3e12d320b14228f701231ae32ddd7dd/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/eb434f61555438d020a6970a5dbf9ee8/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/f6b0e73aa7fa029134665d4dde57e096/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/f719a6e4ff09873cb0ffb06ec9d232f9/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/executed/feeee244a7ce3d60e1a227eb604df823/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/example.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/example.tex +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/index.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/.jupyter_cache/executed/ca90e4df5f4f0583df6554156a68dc7f/base.ipynb +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/independent.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/index.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/tasks.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/test_include.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/tryforerror.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/test_include.qmd +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pyDiffTools.egg-info/dependency_links.txt +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pyDiffTools.egg-info/entry_points.txt +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pyDiffTools.egg-info/requires.txt +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pyDiffTools.egg-info/top_level.txt +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/__init__.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/bibliography.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/browser_lifecycle.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/check_numbers.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/citation_dialog.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/command_registry.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comment_filter_history.json +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comment_functions.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comment_migration.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comment_tags.lua +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comment_tags_margin.lua +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comment_tags_no_comments.lua +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comment_toggle.js +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comments.css +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/comments_author_colors.css +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/completions/git-mergein +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/continuous.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/copy_files.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/diff-doc.js +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/doc_contents.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/__init__.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/comparison.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/dot_to_yaml.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/graph.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/source_jump.js +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/svg-pan-zoom.min.js +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/watch_graph.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/flowchart/wgrph_view.js +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/forward_search.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/git_gd.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/git_gd_history.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/git_gd_image.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/git_gd_qt.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/html_comments.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/html_uncomments.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/line_alignment.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/log_example.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/match_spaces.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/notebook/__init__.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/notebook/display.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/notebook/fast_build.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/notebook/tex_to_qmd.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/onewordify.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/onewordify_undo.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/outline.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/pdf_diff.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/rearrange_tex.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/searchacro.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/separate_comments.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/source_jump.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/split_conflict.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/unseparate_comments.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/update_check.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/wrap_sentences.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/wrapping_options.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/xml2xlsx.vbs +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/pydifftools/zotero.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/setup.cfg +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_bibliography.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_browser_lifecycle.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_check_single_use.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_command_line_help.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_comment_filters.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_comment_migration.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_continuous_shutdown.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_forward_search.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_git_gd_history.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_git_gd_image.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_git_gd_qt.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_git_mergein.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_git_pdf_diff.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_line_alignment.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_pdf_diff.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_qt_lifecycle.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_rrng.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_source_jump.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_tex_to_qmd.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_update_check.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_wrap_check.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_wrapping.py +0 -0
- {pydifftools-0.1.58 → pydifftools-0.1.59}/tests/test_zotero.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.59
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -274,10 +274,20 @@ included are (listed in order of fun/utility):
|
|
|
274
274
|
retaining the exact command of an existing global ``gd`` alias. If none
|
|
275
275
|
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
276
276
|
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
277
|
-
- ``pydifft --add_to_git gd pd tree mergein`` installs any selected subset
|
|
277
|
+
- ``pydifft --add_to_git gd pd tree mergein reattach`` installs any selected subset
|
|
278
278
|
of these global Git aliases in one invocation. Installation appears
|
|
279
279
|
alongside the subcommands in root help; the former per-command
|
|
280
280
|
``--install`` and ``--add-to-git`` flags have been removed.
|
|
281
|
+
- ``pydifft reattach [--path DIRECTORY]`` attaches detached checkouts to
|
|
282
|
+
branches pointing at exactly their current commits, including initialized
|
|
283
|
+
submodules recursively. Remote-only matches create local tracking branches.
|
|
284
|
+
It never resets existing branches or pulls newer commits. With several
|
|
285
|
+
matches it prefers the origin default branch when possible, otherwise it
|
|
286
|
+
reports ambiguity and leaves the checkout detached. A local branch with
|
|
287
|
+
the required name pointing elsewhere is preserved. ``--dry-run`` previews
|
|
288
|
+
changes, ``--no-recursive`` limits the operation to one repository, and
|
|
289
|
+
``--fetch`` refreshes remote refs before matching. Install the global
|
|
290
|
+
``git reattach`` alias with ``pydifft --add_to_git reattach``.
|
|
281
291
|
- ``pydifft mergein BRANCH [--remote REMOTE]`` updates an incoming local
|
|
282
292
|
branch without switching branches, then merges it into the current
|
|
283
293
|
branch. Install ``git mergein`` with ``pydifft --add_to_git mergein``.
|
|
@@ -219,10 +219,20 @@ included are (listed in order of fun/utility):
|
|
|
219
219
|
retaining the exact command of an existing global ``gd`` alias. If none
|
|
220
220
|
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
221
221
|
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
222
|
-
- ``pydifft --add_to_git gd pd tree mergein`` installs any selected subset
|
|
222
|
+
- ``pydifft --add_to_git gd pd tree mergein reattach`` installs any selected subset
|
|
223
223
|
of these global Git aliases in one invocation. Installation appears
|
|
224
224
|
alongside the subcommands in root help; the former per-command
|
|
225
225
|
``--install`` and ``--add-to-git`` flags have been removed.
|
|
226
|
+
- ``pydifft reattach [--path DIRECTORY]`` attaches detached checkouts to
|
|
227
|
+
branches pointing at exactly their current commits, including initialized
|
|
228
|
+
submodules recursively. Remote-only matches create local tracking branches.
|
|
229
|
+
It never resets existing branches or pulls newer commits. With several
|
|
230
|
+
matches it prefers the origin default branch when possible, otherwise it
|
|
231
|
+
reports ambiguity and leaves the checkout detached. A local branch with
|
|
232
|
+
the required name pointing elsewhere is preserved. ``--dry-run`` previews
|
|
233
|
+
changes, ``--no-recursive`` limits the operation to one repository, and
|
|
234
|
+
``--fetch`` refreshes remote refs before matching. Install the global
|
|
235
|
+
``git reattach`` alias with ``pydifft --add_to_git reattach``.
|
|
226
236
|
- ``pydifft mergein BRANCH [--remote REMOTE]`` updates an incoming local
|
|
227
237
|
branch without switching branches, then merges it into the current
|
|
228
238
|
branch. Install ``git mergein`` with ``pydifft --add_to_git mergein``.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.59
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -274,10 +274,20 @@ included are (listed in order of fun/utility):
|
|
|
274
274
|
retaining the exact command of an existing global ``gd`` alias. If none
|
|
275
275
|
is configured, it installs ``!f() { pydifft gd "$@"; }; f``.
|
|
276
276
|
Configure ``difftool.mygvim.cmd`` for the GUI diff tool.
|
|
277
|
-
- ``pydifft --add_to_git gd pd tree mergein`` installs any selected subset
|
|
277
|
+
- ``pydifft --add_to_git gd pd tree mergein reattach`` installs any selected subset
|
|
278
278
|
of these global Git aliases in one invocation. Installation appears
|
|
279
279
|
alongside the subcommands in root help; the former per-command
|
|
280
280
|
``--install`` and ``--add-to-git`` flags have been removed.
|
|
281
|
+
- ``pydifft reattach [--path DIRECTORY]`` attaches detached checkouts to
|
|
282
|
+
branches pointing at exactly their current commits, including initialized
|
|
283
|
+
submodules recursively. Remote-only matches create local tracking branches.
|
|
284
|
+
It never resets existing branches or pulls newer commits. With several
|
|
285
|
+
matches it prefers the origin default branch when possible, otherwise it
|
|
286
|
+
reports ambiguity and leaves the checkout detached. A local branch with
|
|
287
|
+
the required name pointing elsewhere is preserved. ``--dry-run`` previews
|
|
288
|
+
changes, ``--no-recursive`` limits the operation to one repository, and
|
|
289
|
+
``--fetch`` refreshes remote refs before matching. Install the global
|
|
290
|
+
``git reattach`` alias with ``pydifft --add_to_git reattach``.
|
|
281
291
|
- ``pydifft mergein BRANCH [--remote REMOTE]`` updates an incoming local
|
|
282
292
|
branch without switching branches, then merges it into the current
|
|
283
293
|
branch. Install ``git mergein`` with ``pydifft --add_to_git mergein``.
|
|
@@ -70,6 +70,7 @@ pydifftools/git_gd.py
|
|
|
70
70
|
pydifftools/git_gd_history.py
|
|
71
71
|
pydifftools/git_gd_image.py
|
|
72
72
|
pydifftools/git_gd_qt.py
|
|
73
|
+
pydifftools/git_reattach.py
|
|
73
74
|
pydifftools/html_comments.py
|
|
74
75
|
pydifftools/html_uncomments.py
|
|
75
76
|
pydifftools/line_alignment.py
|
|
@@ -116,6 +117,7 @@ tests/test_git_gd_image.py
|
|
|
116
117
|
tests/test_git_gd_qt.py
|
|
117
118
|
tests/test_git_mergein.py
|
|
118
119
|
tests/test_git_pdf_diff.py
|
|
120
|
+
tests/test_git_reattach.py
|
|
119
121
|
tests/test_line_alignment.py
|
|
120
122
|
tests/test_pdf_diff.py
|
|
121
123
|
tests/test_qt_lifecycle.py
|
|
@@ -36,6 +36,7 @@ from .comment_functions import matchingbrackets
|
|
|
36
36
|
from .copy_files import copy_image_files
|
|
37
37
|
from .searchacro import replace_acros
|
|
38
38
|
from .rearrange_tex import run as rearrange_tex_run
|
|
39
|
+
from .git_reattach import reattach # registers branch reattachment
|
|
39
40
|
from .git_gd import gd # registers git difftool review command
|
|
40
41
|
from .pdf_diff import pd, git_pd # registers PDF diff command
|
|
41
42
|
from .git_aliases import (
|
|
@@ -909,7 +910,7 @@ def build_parser():
|
|
|
909
910
|
# argparse does not validate REMAINDER choices; main checks them first.
|
|
910
911
|
subparsers.container.add_argument(
|
|
911
912
|
"--add_to_git", nargs=argparse.REMAINDER, choices=list(GIT_ALIASES),
|
|
912
|
-
help=("Install one or more global Git aliases: gd, pd, tree, mergein "
|
|
913
|
+
help=("Install one or more global Git aliases: gd, pd, tree, mergein, reattach "
|
|
913
914
|
"(without a subcommand)."),
|
|
914
915
|
)
|
|
915
916
|
for name, spec in _COMMAND_SPECS.items():
|
|
@@ -11,10 +11,12 @@ GIT_ALIASES = {
|
|
|
11
11
|
"gd": '!f() { pydifft gd "$@"; }; f',
|
|
12
12
|
"pd": '!f() { pydifft pd --git "$@"; }; f',
|
|
13
13
|
"tree": '!f() { pydifft tree "$@"; }; f',
|
|
14
|
+
"reattach": '!f() { pydifft reattach "$@"; }; f',
|
|
14
15
|
"mergein": '!f() { pydifft mergein "$@"; }; f',
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
|
|
19
|
+
# also used by: pydifftools/command_line.py for global CLI alias installation.
|
|
18
20
|
def install_git_alias(name, command, preserve_existing=False):
|
|
19
21
|
"""Install an alias and its completion, optionally retaining its value."""
|
|
20
22
|
if preserve_existing:
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
"""Attach detached checkouts without changing the selected commits."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
from .command_registry import register_command
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _git(path, *args, allowed=(0,)):
|
|
10
|
+
result = subprocess.run(
|
|
11
|
+
["git", "-C", str(path), *args], capture_output=True, text=True,
|
|
12
|
+
)
|
|
13
|
+
if result.returncode not in allowed:
|
|
14
|
+
raise RuntimeError(result.stderr.strip() or "Git command failed")
|
|
15
|
+
return result.stdout.rstrip("\n")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@register_command(
|
|
19
|
+
"reattach detached repositories to matching local or remote branches",
|
|
20
|
+
description=(
|
|
21
|
+
"Keep each checkout's current commit and attach a branch whose tip "
|
|
22
|
+
"matches it exactly. Includes initialized submodules recursively. "
|
|
23
|
+
"A remote-only match creates a local tracking branch. Existing "
|
|
24
|
+
"branches are never reset. Ambiguous or unmatched checkouts stay "
|
|
25
|
+
"detached. Cached remote branches are used unless --fetch is given."
|
|
26
|
+
),
|
|
27
|
+
help={
|
|
28
|
+
"path": "Repository or a directory inside it (default: current).",
|
|
29
|
+
"no_recursive": "Only inspect this repository, not its submodules.",
|
|
30
|
+
"fetch": "Fetch remote branches before looking for matches.",
|
|
31
|
+
"dry_run": "Show proposed switches without changing anything.",
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
def reattach(path=".", no_recursive=False, fetch=False, dry_run=False):
|
|
35
|
+
"""Find exact branch-tip matches, preserving commits and working files."""
|
|
36
|
+
if fetch and dry_run:
|
|
37
|
+
raise SystemExit("reattach: --fetch cannot be used with --dry-run")
|
|
38
|
+
try:
|
|
39
|
+
root = Path(_git(path, "rev-parse", "--show-toplevel"))
|
|
40
|
+
paths = [root]
|
|
41
|
+
if not no_recursive:
|
|
42
|
+
children = _git(
|
|
43
|
+
root, "submodule", "foreach", "--quiet", "--recursive",
|
|
44
|
+
'printf "%s\\0" "$PWD"',
|
|
45
|
+
)
|
|
46
|
+
paths.extend(Path(p) for p in children.split("\0") if p)
|
|
47
|
+
failed = False
|
|
48
|
+
for checkout in paths:
|
|
49
|
+
label = str(checkout)
|
|
50
|
+
try:
|
|
51
|
+
if _git(
|
|
52
|
+
checkout, "symbolic-ref", "--quiet", "HEAD",
|
|
53
|
+
allowed=(0, 1),
|
|
54
|
+
):
|
|
55
|
+
print(f"{label}: already on a branch; unchanged")
|
|
56
|
+
continue
|
|
57
|
+
if fetch:
|
|
58
|
+
_git(checkout, "fetch", "--all", "--prune",
|
|
59
|
+
"--no-recurse-submodules")
|
|
60
|
+
head = _git(checkout, "rev-parse", "HEAD")
|
|
61
|
+
# {{{ ask Git for exact matches, excluding symbolic refs
|
|
62
|
+
refs = _git(
|
|
63
|
+
checkout, "for-each-ref",
|
|
64
|
+
"--format=%(refname)%00%(symref)", "--points-at", head,
|
|
65
|
+
"refs/heads/", "refs/remotes/",
|
|
66
|
+
)
|
|
67
|
+
matches = [
|
|
68
|
+
line.split("\0")[0] for line in refs.splitlines()
|
|
69
|
+
if line.endswith("\0")
|
|
70
|
+
]
|
|
71
|
+
local = [r for r in matches if r.startswith("refs/heads/")]
|
|
72
|
+
remote = [r for r in matches
|
|
73
|
+
if r.startswith("refs/remotes/")]
|
|
74
|
+
default = _git(
|
|
75
|
+
checkout, "symbolic-ref", "--quiet",
|
|
76
|
+
"refs/remotes/origin/HEAD", allowed=(0, 1),
|
|
77
|
+
)
|
|
78
|
+
default_name = default.removeprefix("refs/remotes/origin/")
|
|
79
|
+
branch = None
|
|
80
|
+
upstream = None
|
|
81
|
+
if local:
|
|
82
|
+
preferred = "refs/heads/" + default_name
|
|
83
|
+
if preferred in local:
|
|
84
|
+
branch = default_name
|
|
85
|
+
elif len(local) == 1:
|
|
86
|
+
branch = local[0].removeprefix("refs/heads/")
|
|
87
|
+
elif remote:
|
|
88
|
+
# Derive names from configured remotes, retaining slashes
|
|
89
|
+
# in branch names and allowing slashes in remote names.
|
|
90
|
+
remotes = sorted(
|
|
91
|
+
_git(checkout, "remote").splitlines(),
|
|
92
|
+
key=len, reverse=True,
|
|
93
|
+
)
|
|
94
|
+
candidates = {}
|
|
95
|
+
for ref in remote:
|
|
96
|
+
for name in remotes:
|
|
97
|
+
prefix = f"refs/remotes/{name}/"
|
|
98
|
+
if ref.startswith(prefix):
|
|
99
|
+
candidates[ref] = ref[len(prefix):]
|
|
100
|
+
break
|
|
101
|
+
if default in candidates:
|
|
102
|
+
upstream = default
|
|
103
|
+
elif len(candidates) == 1:
|
|
104
|
+
upstream = next(iter(candidates))
|
|
105
|
+
elif len(set(candidates.values())) == 1:
|
|
106
|
+
name = next(iter(candidates.values()))
|
|
107
|
+
preferred = "refs/remotes/origin/" + name
|
|
108
|
+
if preferred in candidates:
|
|
109
|
+
upstream = preferred
|
|
110
|
+
if upstream:
|
|
111
|
+
branch = candidates[upstream]
|
|
112
|
+
existing = _git(
|
|
113
|
+
checkout, "show-ref", "--verify", "--hash",
|
|
114
|
+
f"refs/heads/{branch}", allowed=(0, 1, 128),
|
|
115
|
+
)
|
|
116
|
+
if existing:
|
|
117
|
+
print(
|
|
118
|
+
f"{label}: local {branch} points elsewhere; "
|
|
119
|
+
"left detached without resetting it"
|
|
120
|
+
)
|
|
121
|
+
continue
|
|
122
|
+
# }}}
|
|
123
|
+
if branch is None:
|
|
124
|
+
reason = "ambiguous branch matches" if matches else (
|
|
125
|
+
"no branch tip matches this commit"
|
|
126
|
+
)
|
|
127
|
+
print(f"{label}: {reason}; left detached")
|
|
128
|
+
continue
|
|
129
|
+
action = "create tracking branch" if upstream else "switch to"
|
|
130
|
+
print(f"{label}: {action} {branch}")
|
|
131
|
+
if not dry_run:
|
|
132
|
+
if upstream:
|
|
133
|
+
_git(checkout, "switch", "--track", "-c", branch,
|
|
134
|
+
upstream)
|
|
135
|
+
else:
|
|
136
|
+
_git(checkout, "switch", "--no-guess", "--", branch)
|
|
137
|
+
if _git(checkout, "rev-parse", "HEAD") != head:
|
|
138
|
+
raise RuntimeError("branch moved during reattachment")
|
|
139
|
+
except RuntimeError as exc:
|
|
140
|
+
print(f"{label}: {exc}")
|
|
141
|
+
failed = True
|
|
142
|
+
if failed:
|
|
143
|
+
raise SystemExit(1)
|
|
144
|
+
except (OSError, RuntimeError) as exc:
|
|
145
|
+
raise SystemExit(f"reattach: {exc}") from None
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"""Reattachment against real repositories, including remote-only branches."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
import subprocess
|
|
6
|
+
import sys
|
|
7
|
+
import time
|
|
8
|
+
|
|
9
|
+
import pytest
|
|
10
|
+
|
|
11
|
+
from pydifftools.git_reattach import reattach
|
|
12
|
+
from pydifftools import command_line
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def git(path, *args):
|
|
16
|
+
return subprocess.check_output(
|
|
17
|
+
["git", "-C", str(path), *map(str, args)],
|
|
18
|
+
stderr=subprocess.STDOUT, text=True,
|
|
19
|
+
).strip()
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.fixture
|
|
23
|
+
def project(tmp_path, monkeypatch):
|
|
24
|
+
monkeypatch.setenv("GIT_CONFIG_GLOBAL", str(tmp_path / "global"))
|
|
25
|
+
monkeypatch.setenv("GIT_CONFIG_NOSYSTEM", "1")
|
|
26
|
+
monkeypatch.setenv("GIT_AUTHOR_NAME", "Test")
|
|
27
|
+
monkeypatch.setenv("GIT_AUTHOR_EMAIL", "test@example.invalid")
|
|
28
|
+
monkeypatch.setenv("GIT_COMMITTER_NAME", "Test")
|
|
29
|
+
monkeypatch.setenv("GIT_COMMITTER_EMAIL", "test@example.invalid")
|
|
30
|
+
remote = tmp_path / "remote.git"
|
|
31
|
+
seed = tmp_path / "seed"
|
|
32
|
+
work = tmp_path / "work space"
|
|
33
|
+
git(tmp_path, "init", "--bare", "--initial-branch=main", remote)
|
|
34
|
+
git(tmp_path, "clone", remote, seed)
|
|
35
|
+
(seed / "file").write_text("main\n")
|
|
36
|
+
git(seed, "add", "file")
|
|
37
|
+
git(seed, "commit", "-m", "main")
|
|
38
|
+
git(seed, "checkout", "-b", "work/topic")
|
|
39
|
+
(seed / "file").write_text("topic\n")
|
|
40
|
+
git(seed, "commit", "-am", "topic")
|
|
41
|
+
git(seed, "push", "origin", "main", "work/topic")
|
|
42
|
+
git(tmp_path, "clone", remote, work)
|
|
43
|
+
git(work, "checkout", "--detach", "origin/work/topic")
|
|
44
|
+
return seed, work
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def test_remote_only_match_tracks_and_preserves_files(project):
|
|
48
|
+
_, work = project
|
|
49
|
+
before = git(work, "rev-parse", "HEAD")
|
|
50
|
+
(work / "file").write_text("uncommitted edit\n")
|
|
51
|
+
(work / "untracked").write_text("keep\n")
|
|
52
|
+
reattach(str(work))
|
|
53
|
+
assert git(work, "branch", "--show-current") == "work/topic"
|
|
54
|
+
assert git(work, "rev-parse", "--abbrev-ref", "@{upstream}") == (
|
|
55
|
+
"origin/work/topic"
|
|
56
|
+
)
|
|
57
|
+
assert git(work, "rev-parse", "HEAD") == before
|
|
58
|
+
assert (work / "file").read_text() == "uncommitted edit\n"
|
|
59
|
+
assert (work / "untracked").read_text() == "keep\n"
|
|
60
|
+
reattach(str(work))
|
|
61
|
+
assert git(work, "rev-parse", "HEAD") == before
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def test_local_match_and_dry_run(project):
|
|
65
|
+
_, work = project
|
|
66
|
+
git(work, "branch", "topic-local", "HEAD")
|
|
67
|
+
reattach(str(work), dry_run=True)
|
|
68
|
+
assert git(work, "branch", "--show-current") == ""
|
|
69
|
+
reattach(str(work))
|
|
70
|
+
assert git(work, "branch", "--show-current") == "topic-local"
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_origin_default_disambiguates_local_branches(project):
|
|
74
|
+
_, work = project
|
|
75
|
+
git(work, "checkout", "--detach", "origin/main")
|
|
76
|
+
git(work, "branch", "alternative", "HEAD")
|
|
77
|
+
reattach(str(work))
|
|
78
|
+
assert git(work, "branch", "--show-current") == "main"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_default_remote_branch_wins_over_other_remote_matches(project):
|
|
82
|
+
_, work = project
|
|
83
|
+
git(work, "checkout", "--detach", "origin/main")
|
|
84
|
+
git(work, "branch", "-D", "main")
|
|
85
|
+
git(work, "update-ref", "refs/remotes/origin/alternative", "HEAD")
|
|
86
|
+
reattach(str(work))
|
|
87
|
+
assert git(work, "branch", "--show-current") == "main"
|
|
88
|
+
assert git(work, "rev-parse", "--abbrev-ref", "@{u}") == "origin/main"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_ambiguous_remote_matches_are_not_chosen_arbitrarily(project, capsys):
|
|
92
|
+
_, work = project
|
|
93
|
+
git(work, "update-ref", "refs/remotes/origin/also-topic", "HEAD")
|
|
94
|
+
reattach(str(work))
|
|
95
|
+
assert git(work, "branch", "--show-current") == ""
|
|
96
|
+
assert "ambiguous" in capsys.readouterr().out
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_existing_local_branch_is_never_reset(project, capsys):
|
|
100
|
+
_, work = project
|
|
101
|
+
git(work, "branch", "work/topic", "origin/main")
|
|
102
|
+
before = git(work, "rev-parse", "work/topic")
|
|
103
|
+
reattach(str(work))
|
|
104
|
+
assert git(work, "branch", "--show-current") == ""
|
|
105
|
+
assert git(work, "rev-parse", "work/topic") == before
|
|
106
|
+
assert "points elsewhere" in capsys.readouterr().out
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_no_match_stays_at_recorded_commit(project):
|
|
110
|
+
_, work = project
|
|
111
|
+
(work / "file").write_text("unpublished\n")
|
|
112
|
+
git(work, "commit", "-am", "unpublished")
|
|
113
|
+
before = git(work, "rev-parse", "HEAD")
|
|
114
|
+
reattach(str(work))
|
|
115
|
+
assert git(work, "branch", "--show-current") == ""
|
|
116
|
+
assert git(work, "rev-parse", "HEAD") == before
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_non_origin_remote_and_branch_with_slash(project):
|
|
120
|
+
_, work = project
|
|
121
|
+
git(work, "remote", "rename", "origin", "upstream")
|
|
122
|
+
reattach(str(work))
|
|
123
|
+
assert git(work, "rev-parse", "--abbrev-ref", "@{u}") == (
|
|
124
|
+
"upstream/work/topic"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_recursive_submodule_and_cli_registration(project, tmp_path):
|
|
129
|
+
seed, work = project
|
|
130
|
+
parent = tmp_path / "parent"
|
|
131
|
+
git(tmp_path, "init", "--initial-branch=main", parent)
|
|
132
|
+
git(parent, "-c", "protocol.file.allow=always", "submodule", "add",
|
|
133
|
+
str(seed), "child with spaces")
|
|
134
|
+
child = parent / "child with spaces"
|
|
135
|
+
git(child, "checkout", "--detach", "origin/work/topic")
|
|
136
|
+
git(child, "branch", "-D", "work/topic")
|
|
137
|
+
git(parent, "commit", "-am", "child")
|
|
138
|
+
args = command_line.build_parser().parse_args(
|
|
139
|
+
["reattach", "--path", str(parent)]
|
|
140
|
+
)
|
|
141
|
+
args._handler(path=args.path, no_recursive=args.no_recursive,
|
|
142
|
+
fetch=args.fetch, dry_run=args.dry_run)
|
|
143
|
+
assert git(child, "branch", "--show-current") == "work/topic"
|
|
144
|
+
assert git(parent, "branch", "--show-current") == "main"
|
|
145
|
+
assert git(child, "rev-parse", "HEAD") == git(work, "rev-parse", "HEAD")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def test_checked_out_branch_elsewhere_is_not_stolen(project, tmp_path):
|
|
149
|
+
_, work = project
|
|
150
|
+
git(work, "branch", "topic-local", "HEAD")
|
|
151
|
+
git(work, "worktree", "add", tmp_path / "other", "topic-local")
|
|
152
|
+
with pytest.raises(SystemExit):
|
|
153
|
+
reattach(str(work))
|
|
154
|
+
assert git(work, "branch", "--show-current") == ""
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def test_fetch_finds_remote_only_match(project):
|
|
158
|
+
_, work = project
|
|
159
|
+
git(work, "update-ref", "-d", "refs/remotes/origin/work/topic")
|
|
160
|
+
reattach(str(work), fetch=True)
|
|
161
|
+
assert git(work, "branch", "--show-current") == "work/topic"
|
|
162
|
+
assert git(work, "rev-parse", "--abbrev-ref", "@{u}") == (
|
|
163
|
+
"origin/work/topic"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_installed_git_alias_forwards_options(project, tmp_path, monkeypatch):
|
|
168
|
+
_, work = project
|
|
169
|
+
launcher = tmp_path / "pydifft"
|
|
170
|
+
launcher.write_text(
|
|
171
|
+
f"#!{sys.executable}\n"
|
|
172
|
+
"from pydifftools.command_line import main\nmain()\n"
|
|
173
|
+
)
|
|
174
|
+
launcher.chmod(0o755)
|
|
175
|
+
monkeypatch.setenv("PATH", str(tmp_path) + os.pathsep + os.environ["PATH"])
|
|
176
|
+
monkeypatch.setenv("PYTHONPATH", str(Path(__file__).resolve().parents[1]))
|
|
177
|
+
monkeypatch.setenv(
|
|
178
|
+
"PYDIFFTOOLS_UPDATE_CHECK_LAST_RAN_UTC_DATE",
|
|
179
|
+
time.strftime("%Y-%m-%d", time.gmtime()),
|
|
180
|
+
)
|
|
181
|
+
monkeypatch.chdir(work)
|
|
182
|
+
command_line.main(["--add_to_git", "reattach"])
|
|
183
|
+
git(work, "reattach", "--dry-run", "--no-recursive")
|
|
184
|
+
assert git(work, "branch", "--show-current") == ""
|
|
185
|
+
git(work, "reattach", "--no-recursive")
|
|
186
|
+
assert git(work, "branch", "--show-current") == "work/topic"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/__version__.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/.jupyter_cache/global.db
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg
RENAMED
|
File without changes
|
{pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/independent.qmd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/test_include.qmd
RENAMED
|
File without changes
|
{pydifftools-0.1.58 → pydifftools-0.1.59}/example_notebook/project1/subproject1/tryforerror.qmd
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|