Skip to content

Commit 81c299b

Browse files
authored
Merge pull request #429 from lomnido/feat-tmp_bare_repo
new feature: tmp bare repo: show position for DM|FM if SHA1
2 parents 62a5b51 + 6524c9d commit 81c299b

27 files changed

+2858
-208
lines changed

tsrc/cli/__init__.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,26 @@ def resolve_repos_without_workspace(
263263
return repos
264264

265265

266+
def is_match_repo_dest_on_inc_excl(
267+
gac: GroupsAndConstraints,
268+
i_r_d: str,
269+
) -> bool:
270+
if (
271+
(gac.include_regex and re.search(gac.include_regex, i_r_d)) # noqa: W503
272+
or not gac.include_regex # noqa: W503
273+
) and (
274+
(gac.exclude_regex and not re.search(gac.exclude_regex, i_r_d)) # noqa: W503
275+
or not gac.exclude_regex # noqa: W503
276+
):
277+
return True
278+
return False
279+
280+
266281
def resolve_repos_apply_constraints(
267282
repos: List[Repo],
268283
gac: GroupsAndConstraints,
269284
) -> List[Repo]:
285+
# NOTE: code duplication, see Fn above, and above above
270286
"""
271287
Use just constraints on Repos in GroupAndConstraints class
272288
to filter Repos. Consider:

tsrc/cli/dump_manifest.py

Lines changed: 66 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
So we do not have '.tscr/config' or any other '.tsrc' data
1111
(not even Groups if they are not present in Manifest when we updating it)
1212
13-
Siplest way to start a new 'tsrc' project by creating Manifest is to prepare
13+
Simplest way to start a new 'tsrc' project by creating Manifest is to prepare
1414
every repository into some dedicated directory and from there call:
1515
1616
'tsrc dump-manifest --raw .'
@@ -26,7 +26,7 @@
2626
import argparse
2727
import io
2828
from pathlib import Path
29-
from typing import Dict, List, Tuple, Union
29+
from typing import Dict, List, Tuple, Union, cast
3030

3131
import cli_ui as ui
3232
from ruamel.yaml import YAML
@@ -50,7 +50,7 @@
5050
from tsrc.executor import process_items
5151
from tsrc.file_system import make_relative
5252
from tsrc.repo import Repo
53-
from tsrc.status_endpoint import CollectedStatuses, StatusCollector
53+
from tsrc.status_endpoint import CollectedStatuses, Status, StatusCollector
5454
from tsrc.utils import erase_last_line
5555

5656

@@ -86,6 +86,28 @@ def configure_parser(subparser: argparse._SubParsersAction) -> None:
8686
help="Disallow to delete any Repo record from existing Manifest. This have only meaning when on UPDATE operation mode", # noqa: E501
8787
dest="no_repo_delete",
8888
)
89+
parser.add_argument(
90+
"--sha1-only",
91+
action="store_true",
92+
help="Use SHA1 as only value (with branch if available) for every considered Repo. This is particulary useful when we want to point to exact point of Repos states", # noqa: E501
93+
dest="sha1_only",
94+
)
95+
parser.add_argument(
96+
"-X",
97+
"--skip-manifest",
98+
help="Skip manifest repository if found. If not, it is ignored. For this filter to work, the Workspace needs to be present. And it is only applied after the processing of the Repositories", # noqa: E501
99+
dest="skip_manifest",
100+
default=False,
101+
action="store_true",
102+
)
103+
parser.add_argument(
104+
"-M",
105+
"--only-manifest",
106+
help="Only work with manifest repository if found. If not, the Error is thrown that list of Repositories ends up empty. For this filter to work, the Workspace needs to be present. And it is only applied after the processing of the Repositories", # noqa: E501
107+
dest="only_manifest",
108+
default=False,
109+
action="store_true",
110+
)
89111
parser.add_argument(
90112
"-p",
91113
"--preview",
@@ -150,8 +172,6 @@ def __init__(self, a: DumpManifestArgs, num_jobs: int) -> None:
150172

151173
# output data
152174
self.yy: Union[Dict, List, None] = None
153-
self.load_path: Union[Path, None] = None # may be useless
154-
self.save_path: Union[Path, None] = None # may be useless
155175
self.is_updated: Union[bool, None] = None
156176

157177
# everything in regard of args
@@ -177,7 +197,7 @@ def get_data(self) -> None:
177197
self.mris_h = MRISHelpers(repos=repos)
178198
elif self.a.dmod.source_mode == SourceModeEnum.WORKSPACE_DUMP:
179199
statuses, w_repos = self._get_data_get_statuses()
180-
for status in statuses:
200+
for _, status in statuses.items():
181201
if not (
182202
isinstance(status, MissingRepoError)
183203
or isinstance(status, Exception) # noqa: W503
@@ -203,6 +223,27 @@ def _get_data_get_repos(self) -> List[Repo]:
203223
if self.a.dmod.source_path:
204224
mgr = ManifestRawGrabber(self.a, self.a.dmod.source_path)
205225
repos, self.a = mgr.grab(self.num_jobs)
226+
if (
227+
self.a.args.skip_manifest is True
228+
or self.a.args.only_manifest is True # noqa: W503
229+
):
230+
if self.a.dmod.workspace:
231+
repos, _ = self.m_du.filter_repos_bo_manifest(
232+
self.a.dmod.workspace,
233+
self.a.args.skip_manifest,
234+
self.a.args.only_manifest,
235+
repos,
236+
)
237+
else:
238+
if self.a.args.skip_manifest is True:
239+
ui.warning(
240+
"Cannot skip Deep Manifest if there is no Workspace"
241+
)
242+
elif self.a.args.only_manifest is True:
243+
ui.warning(
244+
"Cannot look for Deep Manifest if there is no Workspace"
245+
)
246+
repos = []
206247
except Exception as e:
207248
raise (e)
208249

@@ -212,12 +253,24 @@ def _get_data_get_statuses(self) -> Tuple[CollectedStatuses, List[Repo]]:
212253
if self.a.dmod.workspace:
213254
status_collector = StatusCollector(self.a.dmod.workspace)
214255
w_repos = self.a.dmod.workspace.repos
256+
if self.a.args.skip_manifest is True or self.a.args.only_manifest is True:
257+
w_repos, _ = self.m_du.filter_repos_bo_manifest(
258+
self.a.dmod.workspace,
259+
self.a.args.skip_manifest,
260+
self.a.args.only_manifest,
261+
w_repos,
262+
)
263+
215264
if not w_repos:
216265
raise Exception("Workspace is empty, therefore no valid data")
217266
ui.info_1(f"Collecting statuses of {len(w_repos)} repo(s)")
218267
process_items(w_repos, status_collector, num_jobs=self.num_jobs)
219268
erase_last_line()
220-
return status_collector.statuses, w_repos
269+
# TODO: we may want to get rid of BareStatus, but there should not be one in any anyway
270+
return (
271+
cast(Dict[str, Union[Status, Exception]], status_collector.statuses),
272+
w_repos,
273+
)
221274
return {}, []
222275

223276
def _get_yaml_data(self) -> None:
@@ -240,17 +293,21 @@ def _get_yaml_data(self) -> None:
240293
self.yy, self.is_updated = self.m_du.on_update(
241294
y,
242295
self.mris_h.mris,
296+
self.a.dmod.workspace,
297+
self.a.dmod.manifest_data_options,
243298
self.a.mdo,
244299
self.a.gac,
245300
)
246301

247302
if not self.yy:
248303
raise Exception(
249-
f"Not able to load YAML data from file: '{self.load_path}'"
304+
f"Not able to load YAML data from file: '{self.a.dmod.final_output_path_list.update_on_path}'" # noqa: E501
250305
)
251306

252307
else: # decided: create Manifest YAML data (not loading YAML data)
253-
self.yy = self.m_du.do_create(self.mris_h.mris)
308+
self.yy = self.m_du.do_create(
309+
self.mris_h.mris, self.a.dmod.manifest_data_options
310+
)
254311
if self.yy:
255312
self.is_updated = True
256313

tsrc/cli/manifest.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ def run(args: argparse.Namespace) -> None:
157157
wrs.ready_data(
158158
statuses,
159159
)
160-
wrs.separate_leftover_statuses(workspace.repos)
160+
wrs.separate_statuses(workspace.repos)
161+
wrs.calculate_fields_len()
161162

162163
# only calculate summary when there are some Workspace repos
163164
if workspace.repos:

tsrc/cli/status.py

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import argparse
44
from copy import deepcopy
5-
from typing import Union
5+
from typing import Dict, List, Union, cast
66

77
from tsrc.cli import (
88
add_num_jobs_arg,
@@ -15,8 +15,20 @@
1515
from tsrc.executor import process_items
1616
from tsrc.groups import GroupNotFound
1717
from tsrc.groups_to_find import GroupsToFind
18+
from tsrc.local_tmp_bare_repos import (
19+
prepare_tmp_bare_dm_repos,
20+
process_bare_repos,
21+
ready_tmp_bare_repos,
22+
)
23+
from tsrc.manifest_common_data import ManifestsTypeOfData
1824
from tsrc.pcs_repo import get_deep_manifest_from_local_manifest_pcsrepo
19-
from tsrc.status_endpoint import StatusCollector, StatusCollectorLocalOnly
25+
from tsrc.repo import Repo
26+
from tsrc.status_endpoint import (
27+
BareStatus,
28+
Status,
29+
StatusCollector,
30+
StatusCollectorLocalOnly,
31+
)
2032
from tsrc.status_header import StatusHeader, StatusHeaderDisplayMode
2133
from tsrc.utils import erase_last_line
2234

@@ -32,6 +44,12 @@ def configure_parser(subparser: argparse._SubParsersAction) -> None:
3244
add_workspace_arg(parser)
3345
add_repos_selection_args(parser)
3446
add_num_jobs_arg(parser)
47+
parser.add_argument(
48+
"--show-leftovers-status",
49+
action="store_true",
50+
help="show full GIT status also for leftovers, if there are some, that have valid repository on the filesystem. here hard error about the repository is ignored and no status is displayed", # noqa: E501
51+
dest="show_leftovers_status",
52+
)
3553
parser.add_argument(
3654
"--no-mm",
3755
action="store_false",
@@ -105,12 +123,19 @@ def run(args: argparse.Namespace) -> None:
105123
ignore_group_item=args.ignore_group_item,
106124
)
107125

126+
# DM (if present) + bare DM (if DM and present)
108127
dm = None
128+
bare_dm_repos: List[Repo] = []
109129
if args.use_deep_manifest is True:
110130
dm, gtf = get_deep_manifest_from_local_manifest_pcsrepo(
111131
workspace,
112132
gtf,
113133
)
134+
if dm and args.local_git_only is False:
135+
# this require to check remote
136+
bare_dm_repos = prepare_tmp_bare_dm_repos(
137+
workspace, dm, gtf, num_jobs=get_num_jobs(args)
138+
)
114139

115140
wrs = WorkspaceReposSummary(
116141
workspace,
@@ -119,6 +144,7 @@ def run(args: argparse.Namespace) -> None:
119144
manifest_marker=args.use_manifest_marker,
120145
future_manifest=args.use_future_manifest,
121146
use_same_future_manifest=args.use_same_future_manifest,
147+
show_leftovers_status=args.show_leftovers_status,
122148
)
123149

124150
status_header = StatusHeader(
@@ -137,15 +163,27 @@ def run(args: argparse.Namespace) -> None:
137163
)
138164

139165
repos = deepcopy(workspace.repos)
166+
bare_fm_repos = wrs.get_bare_fm_repos()
167+
bare_fm_repos = ready_tmp_bare_repos(
168+
workspace, ManifestsTypeOfData.FUTURE, bare_fm_repos
169+
)
170+
bare_repos = bare_fm_repos + bare_dm_repos
171+
bare_repos = process_bare_repos(workspace, bare_repos, num_jobs=get_num_jobs(args))
172+
repos += bare_repos
140173

141174
wrs.prepare_repos()
142175

176+
leftovers_repos: List[Repo] = []
143177
if args.strict_on_git_desc is False:
144-
repos += wrs.obtain_leftovers_repos(repos)
178+
leftovers_repos = wrs.obtain_leftovers_repos(repos)
179+
repos += leftovers_repos
145180

146181
if repos:
147182

148-
status_header.report_collecting(len(repos))
183+
# status_header.report_collecting(len(repos))
184+
status_header.report_collecting(
185+
len(workspace.repos), len(leftovers_repos), len(bare_repos)
186+
)
149187

150188
num_jobs = get_num_jobs(args)
151189
process_items(repos, status_collector, num_jobs=num_jobs)
@@ -154,9 +192,11 @@ def run(args: argparse.Namespace) -> None:
154192
statuses = status_collector.statuses
155193

156194
wrs.ready_data(
157-
statuses,
195+
# TODO: this crazines is there due to 'StatusCollectorLocalOnly' is possible
196+
cast(Dict[str, Union[Status, Exception, BareStatus, Exception]], statuses),
158197
)
159-
wrs.separate_leftover_statuses(workspace.repos)
198+
wrs.separate_statuses(bare_repos)
199+
wrs.calculate_fields_len()
160200

161201
# only calculate summary when there are some Workspace repos
162202
if workspace.repos:

0 commit comments

Comments
 (0)