dffs 0.0.5__py3-none-any.whl

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.
dffs/__init__.py ADDED
@@ -0,0 +1 @@
1
+ from .utils import join_pipelines, get_git_root, get_dir_path
dffs/cli.py ADDED
@@ -0,0 +1,9 @@
1
+ from os import environ as env
2
+
3
+ from click import option, argument
4
+
5
+ shell_exec_opt = option('-s', '--shell-executable', help=f'Shell to use for executing commands; defaults to $SHELL')
6
+ no_shell_opt = option('-S', '--no-shell', is_flag=True, help="Don't pass `shell=True` to Python `subprocess`es")
7
+ verbose_opt = option('-v', '--verbose', is_flag=True, help="Log intermediate commands to stderr")
8
+ exec_cmd_opt = option('-x', '--exec-cmd', 'exec_cmds', multiple=True, help='Command(s) to execute before invoking `comm`; alternate syntax to passing commands as positional arguments')
9
+ args = argument('args', metavar='[exec_cmd...] <path1> <path2>', nargs=-1)
@@ -0,0 +1,56 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Tuple
4
+
5
+ from click import option, command
6
+ from utz import process
7
+
8
+ from dffs.cli import args, shell_exec_opt, no_shell_opt, verbose_opt, exec_cmd_opt
9
+ from dffs.utils import join_pipelines
10
+
11
+
12
+ @command('comm-x', short_help='comm two files after running them through a pipeline of other commands', no_args_is_help=True)
13
+ @option('-1', '--exclude-1', is_flag=True, help='Exclude lines only found in the first pipeline')
14
+ @option('-2', '--exclude-2', is_flag=True, help='Exclude lines only found in the second pipeline')
15
+ @option('-3', '--exclude-3', is_flag=True, help='Exclude lines found in both pipelines')
16
+ @option('-i', '--case-insensitive', is_flag=True, help='Case insensitive comparison')
17
+ @shell_exec_opt
18
+ @no_shell_opt
19
+ @verbose_opt
20
+ @exec_cmd_opt
21
+ @args
22
+ def main(
23
+ exclude_1: bool,
24
+ exclude_2: bool,
25
+ exclude_3: bool,
26
+ case_insensitive: bool,
27
+ shell_executable: str | None,
28
+ no_shell: bool,
29
+ verbose: bool,
30
+ exec_cmds: Tuple[str, ...],
31
+ args: Tuple[str, ...],
32
+ ):
33
+ """Select or reject lines common to two input streams, after running each through a pipeline of other commands."""
34
+ if len(args) < 2:
35
+ raise ValueError('Must provide at least two files to comm')
36
+
37
+ *cmds, path1, path2 = args
38
+ cmds = list(exec_cmds) + cmds
39
+ if cmds:
40
+ first, *rest = cmds
41
+ join_pipelines(
42
+ base_cmd=[
43
+ 'comm',
44
+ *(['-1'] if exclude_1 else []),
45
+ *(['-2'] if exclude_2 else []),
46
+ *(['-3'] if exclude_3 else []),
47
+ *(['-i'] if case_insensitive else []),
48
+ ],
49
+ cmds1=[ f'{first} {path1}', *rest ],
50
+ cmds2=[ f'{first} {path2}', *rest ],
51
+ verbose=verbose,
52
+ shell=not no_shell,
53
+ executable=shell_executable,
54
+ )
55
+ else:
56
+ process.run(['comm', path1, path2])
@@ -0,0 +1,57 @@
1
+ from __future__ import annotations
2
+
3
+ import subprocess
4
+ from typing import Tuple
5
+
6
+ from click import option, command
7
+
8
+ from dffs.cli import args, shell_exec_opt, no_shell_opt, verbose_opt, exec_cmd_opt
9
+ from dffs.utils import join_pipelines
10
+
11
+ color_opt = option('-c', '--color', is_flag=True, help='Colorize the output')
12
+ unified_opt = option('-U', '--unified', type=int, help='Number of lines of context to show (passes through to `diff`)')
13
+ ignore_whitespace_opt = option('-w', '--ignore-whitespace', is_flag=True, help="Ignore whitespace differences (pass `-w` to `diff`)")
14
+
15
+
16
+ @command('diff-x', short_help='Diff two files after running them through a pipeline of other commands', no_args_is_help=True)
17
+ @color_opt
18
+ @shell_exec_opt
19
+ @no_shell_opt
20
+ @unified_opt
21
+ @verbose_opt
22
+ @ignore_whitespace_opt
23
+ @exec_cmd_opt
24
+ @args
25
+ def main(
26
+ color: bool,
27
+ shell_executable: str | None,
28
+ no_shell: bool,
29
+ unified: int | None,
30
+ verbose: bool,
31
+ ignore_whitespace: bool,
32
+ exec_cmds: Tuple[str, ...],
33
+ args: Tuple[str, ...],
34
+ ):
35
+ """Diff two files after running them through a pipeline of other commands."""
36
+ if len(args) < 2:
37
+ raise ValueError('Must provide at least two files to diff')
38
+
39
+ *cmds, path1, path2 = args
40
+ cmds = list(exec_cmds) + cmds
41
+ diff_args = [
42
+ *(['-w'] if ignore_whitespace else []),
43
+ *(['-U', str(unified)] if unified is not None else []),
44
+ *(['--color=always'] if color else []),
45
+ ]
46
+ if cmds:
47
+ first, *rest = cmds
48
+ join_pipelines(
49
+ base_cmd=['diff', *diff_args],
50
+ cmds1=[ f'{first} {path1}', *rest ],
51
+ cmds2=[ f'{first} {path2}', *rest ],
52
+ verbose=verbose,
53
+ shell=not no_shell,
54
+ executable=shell_executable,
55
+ )
56
+ else:
57
+ subprocess.run(['diff', *diff_args, path1, path2])
@@ -0,0 +1,110 @@
1
+ from __future__ import annotations
2
+
3
+ import shlex
4
+ from typing import Tuple
5
+
6
+ from click import option, argument, command
7
+ from utz import process, err
8
+
9
+ from dffs.cli import shell_exec_opt, no_shell_opt, verbose_opt, exec_cmd_opt
10
+ from dffs.diff_x import color_opt, unified_opt, ignore_whitespace_opt
11
+ from dffs.utils import join_pipelines
12
+
13
+
14
+ @command('git-diff-x', short_help='Diff a Git-tracked file at two commits (or one commit vs. current worktree), optionally passing both through another command first')
15
+ @color_opt
16
+ @option('-r', '--refspec', help='<commit 1>..<commit 2> (compare two commits) or <commit> (compare <commit> to the worktree)')
17
+ @option('-R', '--ref', help="Diff a specific commit; alias for `-r <ref>^..<ref>`")
18
+ @shell_exec_opt
19
+ @no_shell_opt
20
+ @unified_opt
21
+ @verbose_opt
22
+ @ignore_whitespace_opt
23
+ @exec_cmd_opt
24
+ @argument('args', metavar='[exec_cmd...] [<path> | - [paths...]]', nargs=-1)
25
+ def main(
26
+ color: bool,
27
+ refspec: str | None,
28
+ ref: str | None,
29
+ shell_executable: str | None,
30
+ no_shell: bool,
31
+ unified: int | None,
32
+ verbose: bool,
33
+ ignore_whitespace: bool,
34
+ exec_cmds: Tuple[str, ...],
35
+ args: Tuple[str, ...],
36
+ ):
37
+ """Diff files at two commits, or one commit and the current worktree, after applying an optional command pipeline.
38
+
39
+ Examples:
40
+
41
+ # Compare the number of lines (`wc -l`) in file `foo` at the previous vs. current commit (`-r HEAD^..HEAD`):
42
+
43
+ git diff-x -r HEAD^..HEAD wc -l foo
44
+
45
+ # Colorized (`-c`) diff of `md5sum`s of `foo`, at HEAD (last committed value) vs. the current worktree content:
46
+
47
+ git diff-x -c md5sum foo
48
+
49
+ # Use `-` to separate pipeline commands from paths (when more than one path is to be diffed), e.g. this compares
50
+ the largest 10 numbers in `file{1,2}` (HEAD vs. worktree):
51
+
52
+ git diff-x 'sort -rn' head - file1 file2
53
+ """
54
+ if '-' in args:
55
+ idx = args.index('-')
56
+ cmd_args = args[:idx]
57
+ paths = args[idx+1:]
58
+ else:
59
+ *cmd_args, path = args
60
+ paths = [path]
61
+
62
+ cmds = list(exec_cmds) + list(cmd_args)
63
+ shell = not no_shell
64
+ git_relpath_prefix = process.line('git', 'rev-parse', '--show-prefix', log=False)
65
+
66
+ if refspec and ref:
67
+ raise ValueError("Specify -r/--refspec xor -R/--ref")
68
+ if ref:
69
+ refspec = f'{ref}^..{ref}'
70
+ elif not refspec:
71
+ refspec = 'HEAD'
72
+
73
+ pcs = refspec.split('..', 1)
74
+ if len(pcs) == 1:
75
+ ref1 = pcs[0]
76
+ ref2 = None
77
+ elif len(pcs) == 2:
78
+ ref1, ref2 = pcs
79
+ else:
80
+ raise ValueError(f"Invalid refspec: {refspec}")
81
+
82
+ diff_args = [
83
+ *(['-w'] if ignore_whitespace else []),
84
+ *(['-U', str(unified)] if unified is not None else []),
85
+ *(['--color=always'] if color else []),
86
+ ]
87
+ for path in paths:
88
+ if len(paths) > 1:
89
+ err(path)
90
+ if cmds:
91
+ cmds1 = [ f'git show {ref1}:{git_relpath_prefix}{path}', *cmds ]
92
+ if ref2:
93
+ cmds2 = [ f'git show {ref2}:{git_relpath_prefix}{path}', *cmds ]
94
+ else:
95
+ cmd, *sub_cmds = cmds
96
+ cmds2 = [ f'{cmd} {path}', *sub_cmds ]
97
+ if not shell:
98
+ cmds1 = [ shlex.split(c) for c in cmds1 ]
99
+ cmds2 = [ shlex.split(c) for c in cmds2 ]
100
+
101
+ join_pipelines(
102
+ base_cmd=['diff', *diff_args],
103
+ cmds1=cmds1,
104
+ cmds2=cmds2,
105
+ verbose=verbose,
106
+ shell=not no_shell,
107
+ executable=shell_executable,
108
+ )
109
+ else:
110
+ process.run(['git', 'diff', *diff_args, refspec, '--', path])
dffs/utils.py ADDED
@@ -0,0 +1,73 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import cache
4
+ from os import environ as env, getcwd
5
+ from os.path import relpath
6
+ from subprocess import Popen
7
+
8
+ from utz import err, named_pipes, pipeline, process
9
+
10
+
11
+ @cache
12
+ def get_git_root() -> str:
13
+ return process.line('git', 'rev-parse', '--show-toplevel', log=False)
14
+
15
+
16
+ @cache
17
+ def get_dir_path() -> str:
18
+ return relpath(getcwd(), get_git_root())
19
+
20
+
21
+ def join_pipelines(
22
+ base_cmd: list[str],
23
+ cmds1: list[str],
24
+ cmds2: list[str],
25
+ verbose: bool = False,
26
+ executable: str | None = None,
27
+ **kwargs,
28
+ ):
29
+ """Run two sequences of piped commands, pass their outputs as inputs to a ``base_cmd``.
30
+
31
+ Args:
32
+ base_cmd: Top=level command that takes two positional args (named pipes with the outputs
33
+ of the ``cmds1`` and ``cmds2`` pipelines).
34
+ cmds1: First sequence of commands to pipe together
35
+ cmds2: Second sequence of commands to pipe together
36
+ verbose: Whether to print commands being executed
37
+ executable: Shell to use for executing commands; defaults to $SHELL
38
+ **kwargs: Additional arguments passed to subprocess.Popen
39
+
40
+ Each command sequence will be piped together before being compared.
41
+ For example, if cmds1 = ['cat foo.txt', 'sort'], the function will
42
+ execute 'cat foo.txt | sort' before comparing with cmds2's output.
43
+
44
+ Adapted from https://stackoverflow.com/a/28840955"""
45
+ if executable is None:
46
+ executable = env.get('SHELL')
47
+
48
+ with named_pipes(n=2) as pipes:
49
+ (pipe1, pipe2) = pipes
50
+ join_cmd = [
51
+ *base_cmd,
52
+ pipe1,
53
+ pipe2,
54
+ ]
55
+ proc = Popen(join_cmd)
56
+ processes = [proc]
57
+
58
+ for pipe, cmds in ((pipe1, cmds1), (pipe2, cmds2)):
59
+ if verbose:
60
+ err(f"Running pipeline: {' | '.join(cmds)}")
61
+
62
+ processes += pipeline(
63
+ cmds,
64
+ pipe,
65
+ wait=False,
66
+ executable=executable,
67
+ **kwargs,
68
+ )
69
+
70
+ for p in processes:
71
+ p.wait()
72
+
73
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Runs as Coded
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,280 @@
1
+ Metadata-Version: 2.1
2
+ Name: dffs
3
+ Version: 0.0.5
4
+ Summary: Pipe and diff files: execute shell pipelines against multiple inputs, diff/compare/join results.
5
+ Home-page: https://github.com/runsascoded/dffs
6
+ Author: Ryan Williams
7
+ Author-email: ryan@runsascoded.com
8
+ License: MIT
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE
11
+ Requires-Dist: click
12
+ Requires-Dist: utz>=0.13.0
13
+
14
+ # dffs
15
+ Pipe and diff files: execute shell pipelines against multiple inputs, diff/compare/join results.
16
+
17
+ [![dffs on PyPI](https://img.shields.io/pypi/v/dffs?label=dffs)][PyPI]
18
+ <!-- toc -->
19
+ - [Install](#install)
20
+ - [CLIs](#CLIs)
21
+ - [`diff-x`](#diff-x)
22
+ - [Usage](#diff-x-usage)
23
+ - [Examples](#diff-x-examples)
24
+ - [`comm-x`](#comm-x)
25
+ - [Usage](#comm-x-usage)
26
+ - [Examples](#comm-x-examples)
27
+ - [`git-diff-x`](#git-diff-x)
28
+ - [Usage](#git-diff-x-usage)
29
+ - [Examples](#git-diff-x-examples)
30
+ <!-- /toc -->
31
+
32
+ ## Install <a id="install"></a>
33
+
34
+ ```bash
35
+ pip install dffs
36
+ ```
37
+
38
+ ## CLIs <a id="CLIs"></a>
39
+
40
+ ### `diff-x` <a id="diff-x"></a>
41
+
42
+ #### Usage <a id="diff-x-usage"></a>
43
+ <!-- `bmdf diff-x` -->
44
+ ```bash
45
+ diff-x
46
+ # Usage: diff-x [OPTIONS] [exec_cmd...] <path1> <path2>
47
+ #
48
+ # Diff two files after running them through a pipeline of other commands.
49
+ #
50
+ # Options:
51
+ # -c, --color Colorize the output
52
+ # -s, --shell-executable TEXT Shell to use for executing commands; defaults
53
+ # to $SHELL
54
+ # -S, --no-shell Don't pass `shell=True` to Python
55
+ # `subprocess`es
56
+ # -U, --unified INTEGER Number of lines of context to show (passes
57
+ # through to `diff`)
58
+ # -v, --verbose Log intermediate commands to stderr
59
+ # -w, --ignore-whitespace Ignore whitespace differences (pass `-w` to
60
+ # `diff`)
61
+ # -x, --exec-cmd TEXT Command(s) to execute before invoking `comm`;
62
+ # alternate syntax to passing commands as
63
+ # positional arguments
64
+ # --help Show this message and exit.
65
+ ```
66
+
67
+ #### Examples <a id="diff-x-examples"></a>
68
+
69
+ Given two similar JSON objects, where one is compact and the other is pretty-printed:
70
+ ```bash
71
+ echo '{"a":1,"b":2}' > 1.json
72
+ echo '{"a":1,"b":3}' | jq > 2.json
73
+ ```
74
+
75
+ `diff {1,2}.json` outputs the entirety of both objects:
76
+ ```diff
77
+ 1c1,4
78
+ < {"a":1,"b":2}
79
+ ---
80
+ > {
81
+ > "a": 1,
82
+ > "b": 3
83
+ > }
84
+ ```
85
+
86
+ `diff-x 'jq .' {1,2}.json` pretty-prints each side before `diff`ing:
87
+ ```diff
88
+ 3c3
89
+ < "b": 2
90
+ ---
91
+ > "b": 3
92
+ ```
93
+
94
+ ### `comm-x` <a id="comm-x"></a>
95
+ `comm` essentially performs set intersection/difference; `comm-x` allows you to run a pipeline of commands on each input, before comparing them.
96
+
97
+ #### Usage <a id="comm-x-usage"></a>
98
+ <!-- `bmdf comm-x` -->
99
+ ```bash
100
+ comm-x
101
+ # Usage: comm-x [OPTIONS] [exec_cmd...] <path1> <path2>
102
+ #
103
+ # Select or reject lines common to two input streams, after running each
104
+ # through a pipeline of other commands.
105
+ #
106
+ # Options:
107
+ # -1, --exclude-1 Exclude lines only found in the first pipeline
108
+ # -2, --exclude-2 Exclude lines only found in the second pipeline
109
+ # -3, --exclude-3 Exclude lines found in both pipelines
110
+ # -i, --case-insensitive Case insensitive comparison
111
+ # -s, --shell-executable TEXT Shell to use for executing commands; defaults
112
+ # to $SHELL
113
+ # -S, --no-shell Don't pass `shell=True` to Python
114
+ # `subprocess`es
115
+ # -v, --verbose Log intermediate commands to stderr
116
+ # -x, --exec-cmd TEXT Command(s) to execute before invoking `comm`;
117
+ # alternate syntax to passing commands as
118
+ # positional arguments
119
+ # --help Show this message and exit.
120
+ ```
121
+
122
+ #### Examples <a id="comm-x-examples"></a>
123
+ Given two similar lists of numbers, but in different orders:
124
+ ```bash
125
+ seq 10 > 1.txt
126
+ seq 10 -2 0 > 2.txt
127
+ ```
128
+
129
+ `comm` outputs gibberish, because the files aren't in sorted order:
130
+ <!-- `bmdf comm 1.txt 2.txt` -->
131
+ ```bash
132
+ comm 1.txt 2.txt
133
+ # 1
134
+ # 10
135
+ # 2
136
+ # 3
137
+ # 4
138
+ # 5
139
+ # 6
140
+ # 7
141
+ # 8
142
+ # comm: file 2 is not in sorted order
143
+ # 6
144
+ # 4
145
+ # 2
146
+ # 0
147
+ # 9
148
+ # comm: file 1 is not in sorted order
149
+ # 10
150
+ # comm: input is not in sorted order
151
+ ```
152
+
153
+ `comm-x sort` sorts each file first:
154
+ <!-- `bmdf comm-x sort 1.txt 2.txt` -->
155
+ ```bash
156
+ comm-x sort 1.txt 2.txt
157
+ # 0
158
+ # 1
159
+ # 10
160
+ # 2
161
+ # 3
162
+ # 4
163
+ # 5
164
+ # 6
165
+ # 7
166
+ # 8
167
+ # 9
168
+ ```
169
+
170
+ ### `git-diff-x` <a id="git-diff-x"></a>
171
+
172
+ #### Usage <a id="git-diff-x-usage"></a>
173
+ <!-- `bmdf -- git-diff-x --help` -->
174
+ ```bash
175
+ git-diff-x --help
176
+ # Usage: git-diff-x [OPTIONS] [exec_cmd...] [<path> | - [paths...]]
177
+ #
178
+ # Diff files at two commits, or one commit and the current worktree, after
179
+ # applying an optional command pipeline.
180
+ #
181
+ # Examples:
182
+ #
183
+ # # Compare the number of lines (`wc -l`) in file `foo` at the previous vs.
184
+ # current commit (`-r HEAD^..HEAD`):
185
+ #
186
+ # git diff-x -r HEAD^..HEAD wc -l foo
187
+ #
188
+ # # Colorized (`-c`) diff of `md5sum`s of `foo`, at HEAD (last committed
189
+ # value) vs. the current worktree content:
190
+ #
191
+ # git diff-x -c md5sum foo
192
+ #
193
+ # # Use `-` to separate pipeline commands from paths (when more than one path
194
+ # is to be diffed), e.g. this compares the largest 10 numbers in `file{1,2}`
195
+ # (HEAD vs. worktree):
196
+ #
197
+ # git diff-x 'sort -rn' head - file1 file2
198
+ #
199
+ # Options:
200
+ # -c, --color Colorize the output
201
+ # -r, --refspec TEXT <commit 1>..<commit 2> (compare two commits) or
202
+ # <commit> (compare <commit> to the worktree)
203
+ # -R, --ref TEXT Diff a specific commit; alias for `-r
204
+ # <ref>^..<ref>`
205
+ # -s, --shell-executable TEXT Shell to use for executing commands; defaults
206
+ # to $SHELL
207
+ # -S, --no-shell Don't pass `shell=True` to Python
208
+ # `subprocess`es
209
+ # -U, --unified INTEGER Number of lines of context to show (passes
210
+ # through to `diff`)
211
+ # -v, --verbose Log intermediate commands to stderr
212
+ # -w, --ignore-whitespace Ignore whitespace differences (pass `-w` to
213
+ # `diff`)
214
+ # -x, --exec-cmd TEXT Command(s) to execute before invoking `comm`;
215
+ # alternate syntax to passing commands as
216
+ # positional arguments
217
+ # --help Show this message and exit.
218
+ ```
219
+
220
+ #### Examples <a id="git-diff-x-examples"></a>
221
+ Compare line-count (`wc -l`) of this README, before and after commit `8b7a761`:
222
+ <!-- `bmdf -- git-diff-x -R 8b7a761 'wc -l' README.md` -->
223
+ ```bash
224
+ git-diff-x -R 8b7a761 'wc -l' README.md
225
+ # 1c1
226
+ # < 16
227
+ # ---
228
+ # > 206
229
+ ```
230
+
231
+ Examples from `--help` above:
232
+ ```bash
233
+ # Compare the number of lines (`wc -l`) in file `foo` at the previous vs. current commit
234
+ # (`-R HEAD` is equivalent to `-r HEAD^..HEAD`).
235
+ git diff-x -R HEAD wc -l foo
236
+
237
+ # Colorized (`-c`) diff of `md5sum`s of `foo`, at HEAD (last committed value) vs. the current
238
+ # worktree content.
239
+ git diff-x -c md5sum foo
240
+
241
+ # Use `-` to separate pipeline commands from paths (when more than one path is to be diffed),
242
+ # e.g. this compares the largest 10 numbers in `file{1,2}` (HEAD vs. worktree):
243
+ git diff-x 'sort -rn' head - file1 file2
244
+ ```
245
+
246
+ I use `git-diff-x` via several Git and Bash aliases:
247
+
248
+ [`.gitconfig`][diff-x git configs]:
249
+ ```.gitconfig
250
+ [alias]
251
+ ; pip install dffs
252
+ dx = diff-x
253
+ dxc = diff-x -c
254
+ dxcr = diff-x -cR
255
+ dxcrr = diff-x -cr
256
+ dxr = diff-x -R
257
+ dxrr = diff-x -r
258
+ dxw = diff-x -w
259
+ dxwr = diff-x -wR
260
+ dxwrr = diff-x -wr
261
+ ```
262
+
263
+ [`.git-rc`][diff-x aliases]:
264
+ ```bash
265
+ alias gdx="g dx"
266
+ alias gdxc="g dxc"
267
+ alias gdxcr="g dxcr"
268
+ alias gdxcrr="g dxcrr"
269
+ alias gdxr="g dxr"
270
+ alias gdxrr="g dxrr"
271
+ alias gdxw="g dxw"
272
+ alias gdxwr="g dxwr"
273
+ alias gdxwrr="g dxwrr"
274
+ ```
275
+
276
+ [`jq`]: https://stedolan.github.io/jq/
277
+ [PyPI]: https://pypi.org/project/dffs/
278
+
279
+ [diff-x git configs]: https://github.com/ryan-williams/git-helpers/blob/5f27c2e4e88e3e14ede21483c998bdbe2cfccc6f/diff/.gitconfig#L64-L73
280
+ [diff-x aliases]: https://github.com/ryan-williams/git-helpers/blob/5f27c2e4e88e3e14ede21483c998bdbe2cfccc6f/diff/.git-rc#L59-L67
@@ -0,0 +1,12 @@
1
+ dffs/__init__.py,sha256=89i9IY6_uQ0Wj_OmzChDfzN3uGlobCFckMejrIs1cnY,62
2
+ dffs/cli.py,sha256=SRkeSyWuXLe05orCrK_X8gg6F2eDT4T84OB30OQrPGE,655
3
+ dffs/utils.py,sha256=g35SCST65ft_5_2zXKwPvbQdlEIXSu13l0Ita_T_Ae4,2088
4
+ dffs/comm_x/__init__.py,sha256=tUFC21cmBkmUr0nOn6nlghFtGzIsDeXDJkNpEDGeZTY,1906
5
+ dffs/diff_x/__init__.py,sha256=lxecRKUakou3Sg8nZFTLTgISPIZuEKnJ1v9_2htdI4A,1832
6
+ dffs/git_diff_x/__init__.py,sha256=aOAQwa2DdrTlJrxF8mIP8pWqEFc8yAZaaag9DcUomZ4,3608
7
+ dffs-0.0.5.dist-info/LICENSE,sha256=tNEc4t-f14dXtZppT5u1eRdYgvwLcFY-ZCn_TmhhXQ4,1070
8
+ dffs-0.0.5.dist-info/METADATA,sha256=XvFp3Co0GqR5vs4bnkAsNN-LtFsxLdPajiBEgqdqSRc,8328
9
+ dffs-0.0.5.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
10
+ dffs-0.0.5.dist-info/entry_points.txt,sha256=8NiFTRDOkvSNaNCHGupz2OkfBZqPKOj-GpisKJufR3I,104
11
+ dffs-0.0.5.dist-info/top_level.txt,sha256=FkFAcPfGiM1znGhny7sQpbccZHGD3lAxD5hyhtlONU4,5
12
+ dffs-0.0.5.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.45.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,4 @@
1
+ [console_scripts]
2
+ comm-x = dffs.comm_x:main
3
+ diff-x = dffs.diff_x:main
4
+ git-diff-x = dffs.git_diff_x:main
@@ -0,0 +1 @@
1
+ dffs