comparison mercurial/configuration/command.py @ 52417:c97e0fd26225

config: move edition code in its own module We start to move code related to the command outside of the main commands modules for clarity. This also highlight some flaw in this code and the new flag are missing some error handling. However we will deal with them later. This move removes the needs for a few module import in the `commands.py` which I see as a good sign.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Mon, 21 Oct 2024 14:05:14 +0200
parents
children e98cea8fc858
comparison
equal deleted inserted replaced
52416:0a81f3ef054c 52417:c97e0fd26225
1 # Gather code related to command dealing with configuration.
2
3 from __future__ import annotations
4
5 import os
6
7 from typing import Any, Dict, Optional
8
9 from ..i18n import _
10
11 from .. import (
12 cmdutil,
13 error,
14 requirements,
15 ui as uimod,
16 util,
17 vfs as vfsmod,
18 )
19
20 from . import rcutil
21
22 EDIT_FLAG = 'edit'
23
24
25 # keep typing simple for now
26 ConfigLevelT = str
27 LEVEL_USER = 'user' # "user" is the default level and never passed explicitly
28 LEVEL_LOCAL = 'local'
29 LEVEL_GLOBAL = 'global'
30 LEVEL_SHARED = 'shared'
31 LEVEL_NON_SHARED = 'non_shared'
32 EDIT_LEVELS = (
33 LEVEL_USER,
34 LEVEL_LOCAL,
35 LEVEL_GLOBAL,
36 LEVEL_SHARED,
37 LEVEL_NON_SHARED,
38 )
39
40
41 def find_edit_level(
42 ui: uimod.ui, repo, opts: Dict[str, Any]
43 ) -> Optional[ConfigLevelT]:
44 """return the level we should edit, if any.
45
46 Parse the command option to detect when an edit is requested, and if so the
47 configuration level we should edit.
48 """
49 if opts.get(EDIT_FLAG) or any(opts.get(o) for o in EDIT_LEVELS):
50 cmdutil.check_at_most_one_arg(opts, *EDIT_LEVELS)
51 for level in EDIT_LEVELS:
52 if opts.get(level):
53 return level
54 return EDIT_LEVELS[0]
55 return None
56
57
58 def edit_config(ui: uimod.ui, repo, level: ConfigLevelT) -> None:
59 """let the user edit configuration file for the given level"""
60
61 if level == LEVEL_USER:
62 paths = rcutil.userrcpath()
63 elif level == LEVEL_GLOBAL:
64 paths = rcutil.systemrcpath()
65 elif level == LEVEL_LOCAL:
66 if not repo:
67 raise error.InputError(_(b"can't use --local outside a repository"))
68 paths = [repo.vfs.join(b'hgrc')]
69 elif level == LEVEL_NON_SHARED:
70 paths = [repo.vfs.join(b'hgrc-not-shared')]
71 elif level == LEVEL_SHARED:
72 if not repo.shared():
73 raise error.InputError(
74 _(b"repository is not shared; can't use --shared")
75 )
76 if requirements.SHARESAFE_REQUIREMENT not in repo.requirements:
77 raise error.InputError(
78 _(
79 b"share safe feature not enabled; "
80 b"unable to edit shared source repository config"
81 )
82 )
83 paths = [vfsmod.vfs(repo.sharedpath).join(b'hgrc')]
84 else:
85 msg = 'unknown config level: %s' % level
86 raise error.ProgrammingError(msg)
87
88 for f in paths:
89 if os.path.exists(f):
90 break
91 else:
92 if LEVEL_GLOBAL:
93 samplehgrc = uimod.samplehgrcs[b'global']
94 elif LEVEL_LOCAL:
95 samplehgrc = uimod.samplehgrcs[b'local']
96 else:
97 samplehgrc = uimod.samplehgrcs[b'user']
98
99 f = paths[0]
100 util.writefile(f, util.tonativeeol(samplehgrc))
101
102 editor = ui.geteditor()
103 ui.system(
104 b"%s \"%s\"" % (editor, f),
105 onerr=error.InputError,
106 errprefix=_(b"edit failed"),
107 blockedtag=b'config_edit',
108 )