diff options
Diffstat (limited to '')
-rw-r--r-- | .gitattributes | 1 | ||||
-rw-r--r-- | .gitignore | 19 | ||||
-rw-r--r-- | pyproject.toml | 1 | ||||
-rw-r--r-- | src/debputy/analysis/debian_dir.py | 54 | ||||
-rw-r--r-- | src/debputy/commands/debputy_cmd/lint_and_lsp_cmds.py | 10 | ||||
-rw-r--r-- | src/debputy/lsp/lsp_debian_control_reference_data.py | 42 | ||||
-rw-r--r-- | src/debputy/lsp/lsp_features.py | 23 |
7 files changed, 106 insertions, 44 deletions
diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..d9bd16b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.py text eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..34b57ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +__pycache__ +.pytest_cache +.coverage +htmlcov +*.pyc +*.pyo +*~ + +local +local-test + +*.deb + +debian/dh-rootless +debian/.debhelper +debian/debhelper-build-stamp +debian/*.substvars +debian/files +debian/*.debhelper.log diff --git a/pyproject.toml b/pyproject.toml index f0e8427..1fcca4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,7 @@ branch = true source = ["."] omit = [ + "*/debputy/lsp/vendoring/*", "*/lib/python*/*", "*/dist-packages/*", "*/tests/*", diff --git a/src/debputy/analysis/debian_dir.py b/src/debputy/analysis/debian_dir.py index 68a5c1b..d63b0c9 100644 --- a/src/debputy/analysis/debian_dir.py +++ b/src/debputy/analysis/debian_dir.py @@ -15,6 +15,7 @@ from typing import ( Iterator, TypedDict, NotRequired, + FrozenSet, ) from debputy.analysis import REFERENCE_DATA_TABLE @@ -277,12 +278,49 @@ def _kpf_install_pattern( return ppkpf.info.get("install_pattern") +def _parse_dh_cmd_list( + cmd_list: Optional[List[Union[Mapping[str, Any], object]]] +) -> Iterable[str]: + if not isinstance(cmd_list, list): + return + + for command in cmd_list: + if not isinstance(command, dict): + continue + command_name = command.get("command") + if isinstance(command_name, str): + yield command_name + + +def _resolve_active_and_inactive_dh_commands( + dh_rules_addons: Iterable[str], +) -> Tuple[FrozenSet[str], FrozenSet[str]]: + cmd = ["dh_assistant", "list-commands", "--output-format=json"] + if dh_rules_addons: + addons = ",".join(dh_rules_addons) + cmd.append(f"--with={addons}") + try: + output = subprocess.check_output( + cmd, + stderr=subprocess.DEVNULL, + ) + except (subprocess.CalledProcessError, FileNotFoundError): + return frozenset(), frozenset() + else: + result = json.loads(output) + active_commands = frozenset(_parse_dh_cmd_list(result.get("commands"))) + disabled_commands = frozenset( + _parse_dh_cmd_list(result.get("disabled-commands")) + ) + return active_commands, disabled_commands + + def _resolve_debhelper_config_files( debian_dir: VirtualPath, binary_packages: Mapping[str, BinaryPackage], debputy_plugin_metadata: DebputyPluginMetadata, dh_ppf_docs: Dict[str, PluginProvidedKnownPackagingFile], - dh_rules_addons: Iterable[str], + dh_rules_addons: Sequence[str], dh_compat_level: int, saw_dh: bool, ) -> Tuple[List[PackagerProvidedFile], Optional[object], int]: @@ -311,6 +349,7 @@ def _resolve_debhelper_config_files( "config-files", [] ) issues = result.get("issues") + active_commands, _ = _resolve_active_and_inactive_dh_commands(dh_rules_addons) for config_file in config_files: if not isinstance(config_file, dict): continue @@ -369,6 +408,8 @@ def _resolve_debhelper_config_files( else: continue is_active = command.get("is-active", True) + if is_active is None and command_name in active_commands: + is_active = True if not isinstance(is_active, bool): continue if is_active: @@ -396,6 +437,13 @@ def _resolve_debhelper_config_files( "packageless_is_fallback_for_all_packages", False, ) + has_active_command = ( + ppkpf.info.get("has_active_command", False) if saw_dh else False + ) + if not has_active_command: + dh_cmds = ppkpf.info.get("debhelper_commands") + if dh_cmds: + has_active_command = any(c in active_commands for c in dh_cmds) dh_ppfs[stem] = _fake_PPFClassSpec( debputy_plugin_metadata, stem, @@ -404,9 +452,7 @@ def _resolve_debhelper_config_files( default_priority=default_priority, post_formatting_rewrite=post_formatting_rewrite, packageless_is_fallback_for_all_packages=packageless_is_fallback_for_all_packages, - has_active_command=( - ppkpf.info.get("has_active_command", False) if saw_dh else False - ), + has_active_command=has_active_command, ) all_dh_ppfs = list( flatten_ppfs( diff --git a/src/debputy/commands/debputy_cmd/lint_and_lsp_cmds.py b/src/debputy/commands/debputy_cmd/lint_and_lsp_cmds.py index e8e380e..46b536b 100644 --- a/src/debputy/commands/debputy_cmd/lint_and_lsp_cmds.py +++ b/src/debputy/commands/debputy_cmd/lint_and_lsp_cmds.py @@ -246,9 +246,13 @@ def lsp_describe_features(context: CommandContext) -> None: from debputy.lsp.lsp_self_check import assert_can_start_lsp - assert_can_start_lsp() - - from debputy.lsp.lsp_features import describe_lsp_features + try: + from debputy.lsp.lsp_features import describe_lsp_features + except ImportError: + assert_can_start_lsp() + raise AssertionError( + "Cannot load the language server features but `assert_can_start_lsp` did not fail" + ) describe_lsp_features(context) diff --git a/src/debputy/lsp/lsp_debian_control_reference_data.py b/src/debputy/lsp/lsp_debian_control_reference_data.py index 9a589bf..1e32d3c 100644 --- a/src/debputy/lsp/lsp_debian_control_reference_data.py +++ b/src/debputy/lsp/lsp_debian_control_reference_data.py @@ -2874,12 +2874,13 @@ BINARY_FIELDS = _fields( Conflicts: bar ``` - Please check the description of the **Breaks** field for when you would use **Breaks** vs. - **Conflicts**. + Please see https://wiki.debian.org/PackageTransition for when to uses **Breaks**, **Conflicts**, + or/and **Replaces**. Note if a package conflicts with itself (indirectly or via **Provides**), then it is using a special rule for **Conflicts**. See section - 7.6.2 "[Replacing whole packages, forcing their removal]" in the Debian Policy Manual. + 7.6.2 "[Replacing whole packages, forcing their removal]" in the Debian Policy Manual for the + details. [Replacing whole packages, forcing their removal]: https://www.debian.org/doc/debian-policy/ch-relationships.html#replacing-whole-packages-forcing-their-removal """ @@ -2902,31 +2903,12 @@ BINARY_FIELDS = _fields( Breaks: bar (<= 1.0~) ```` - **Breaks vs. Conflicts**: + Please see https://wiki.debian.org/PackageTransition for when to uses **Breaks**, **Conflicts**, or/and + **Replaces**. - * I moved files from **foo** to **bar** in version X, what should I do? - - Add `Breaks: foo (<< X~)` + `Replaces: foo (<< X~)` to **bar** - - * Upgrading **bar** while **foo** is version X or less causes **foo** or **bar** to break. - How do I solve this? - - Add `Breaks: foo (<< X~)` to **bar** - - * The **foo** and **bar** packages provide the same functionality (interface) but different - implementations and there can be at most one of them. What should I do? - - See section 7.6.2 [Replacing whole packages, forcing their removal] in the Debian Policy Manual. - - * How to handle when **foo** and **bar** packages are unrelated but happen to provide the same binary? - - Attempt to resolve the name conflict by renaming the clashing files in question on either (or both) sides. - - Note the use of *~* in version numbers in the answers are generally used to ensure this works correctly in + Note the use of *~* in version numbers in the example is used to ensure this works correctly in case of a backports (in the Debian archive), where the package is rebuilt with the "~bpo" suffix in its version. - - [Replacing whole packages, forcing their removal]: https://www.debian.org/doc/debian-policy/ch-relationships.html#replacing-whole-packages-forcing-their-removal """ ), ), @@ -2939,7 +2921,7 @@ BINARY_FIELDS = _fields( This package either replaces another package or overwrites files that used to be provided by another package. - **Attention**: The `Replaces` field is **always** used with either `Breaks` or `Conflicts` field. + **Attention**: The `Replaces` field should **always** used with either `Breaks` or `Conflicts` field. **Example**: ``` @@ -2952,8 +2934,12 @@ BINARY_FIELDS = _fields( Breaks: foo (<< 1.2-3~) ``` - Please check the description of the `Breaks` field for when you would use `Breaks` vs. `Conflicts`. - It also covers common uses of `Replaces`. + Please see https://wiki.debian.org/PackageTransition for when to uses **Breaks**, **Conflicts**, + or/and **Replaces**. + + Note the use of *~* in version numbers in the example is used to ensure this works correctly in + case of a backports (in the Debian archive), where the package is rebuilt with the "~bpo" suffix in its + version. """ ), ), diff --git a/src/debputy/lsp/lsp_features.py b/src/debputy/lsp/lsp_features.py index 800f738..c513523 100644 --- a/src/debputy/lsp/lsp_features.py +++ b/src/debputy/lsp/lsp_features.py @@ -320,18 +320,23 @@ def describe_lsp_features(context: CommandContext) -> None: print("General features:") for self_check in LSP_CHECKS: is_ok = self_check.test() - assert not self_check.is_mandatory or is_ok - if self_check.is_mandatory: - continue if is_ok: print(f" * {self_check.feature}: {fo.colored('enabled', fg='green')}") else: - disabled = fo.colored( - "disabled", - fg="yellow", - bg="black", - style="bold", - ) + if self_check.is_mandatory: + disabled = fo.colored( + "missing", + fg="red", + bg="black", + style="bold", + ) + else: + disabled = fo.colored( + "disabled", + fg="yellow", + bg="black", + style="bold", + ) if self_check.how_to_fix: print(f" * {self_check.feature}: {disabled}") |