Skip to content

Commit 7b6de99

Browse files
committed
Merge branch 'update_submodules_cesm30alpha07g' of github.com:ekluzek/CTSM into update_submodules_cesm30alpha07g
2 parents e436730 + b2f82c7 commit 7b6de99

24 files changed

+1583
-687
lines changed

.gitmodules

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,16 @@ fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git
7575

7676
[submodule "cime"]
7777
path = cime
78-
#url = https://github.com/ESMCI/cime
79-
url = https://github.com/ekluzek/cime
80-
#fxtag = cime6.1.143
81-
#fxtag = allow_colon_for_input_pathname_4738
82-
fxtag = fe5bf83aa4a69f88f0ee91e528dee410e7b11dac
78+
url = https://github.com/ESMCI/cime
79+
fxtag = cime6.1.144
8380
fxrequired = ToplevelRequired
8481
# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed
8582
fxDONOTUSEurl = https://github.com/ESMCI/cime
8683

8784
[submodule "cmeps"]
8885
path = components/cmeps
89-
#url = https://github.com/ESCOMP/CMEPS.git
90-
url = https://github.com/ekluzek/CMEPS.git
91-
#fxtag = cmeps1.1.24
92-
#fxtag = errors_to_cesmlog_524_runtype_branch_525_cpl_inputdatalist_526
93-
fxtag = 3497948aec564770a7acdec175c5524f50d49677
86+
url = https://github.com/ESCOMP/CMEPS.git
87+
fxtag = cmeps1.1.24
9488
fxrequired = ToplevelRequired
9589
# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed
9690
fxDONOTUSEurl = https://github.com/ESCOMP/CMEPS.git

.lib/git-fleximod/.github/workflows/pytest.yaml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ jobs:
7373
- run: |
7474
git config --global user.name "${GITHUB_ACTOR}"
7575
git config --global user.email "${GITHUB_ACTOR_ID}+${GITHUB_ACTOR}@users.noreply.github.com"
76-
poetry run pytest
77-
- name: Setup tmate session
78-
if: ${{ failure() }}
79-
uses: mxschmitt/action-tmate@v3
80-
76+
poetry run pytest --doctest-modules
77+
# - name: Setup tmate session
78+
# if: ${{ failure() }}
79+
# uses: mxschmitt/action-tmate@v3

.lib/git-fleximod/.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ exclude: ^utils/.*$
22

33
repos:
44
- repo: https://github.com/pre-commit/pre-commit-hooks
5-
rev: v4.0.1
5+
rev: v6.0.0
66
hooks:
77
- id: end-of-file-fixer
88
- id: trailing-whitespace

.lib/git-fleximod/CODE_OF_CONDUCT.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Examples of behaviors that contribute to a positive environment include:
1717
* Communicate openly with respect for others, critiquing ideas rather than individuals and gracefully accepting criticism
1818
* Acknowledging the contributions of others
1919
* Avoid personal attacks directed toward other participants
20-
* Be mindful of your surroundings and of your fellow participants
20+
* Be mindful of your surroundings and of your fellow participants
2121
* Alert UCAR staff and suppliers/vendors if you notice a dangerous situation or someone in distress
2222
* Respect the rules and policies of the project and venue
2323

@@ -29,7 +29,7 @@ Examples of unacceptable behavior include, but are not limited to:
2929
* Personal attacks directed at other guests, members, participants, etc.
3030
* Publishing others' private information, such as a physical or electronic address, without explicit permission
3131
* Alarming, intimidating, threatening, or hostile comments or conduct
32-
* Inappropriate use of nudity and/or sexual images
32+
* Inappropriate use of nudity and/or sexual images
3333
* Threatening or stalking anyone, including a participant
3434
* Other conduct which could reasonably be considered inappropriate in a professional setting
3535

@@ -60,7 +60,7 @@ the [Attribution](#attribution) section.
6060
## Reporting
6161
Instances of unacceptable behavior can be brought to the attention of the project administrator(s) who may take any action as
6262
outlined in the [Consequences](#consequences) section below.
63-
However, making a report to a project administrator is not considered an 'official report' to UCAR.
63+
However, making a report to a project administrator is not considered an 'official report' to UCAR.
6464

6565
Instances of unacceptable behavior may also be reported directly to UCAR pursuant to [UCAR's Harassment Reporting and Complaint
6666
Procedure](https://www2.fin.ucar.edu/procedures/hr/harassment-reporting-and-complaint-procedure), or anonymously through [UCAR's

.lib/git-fleximod/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Git-fleximod is a Python-based tool that extends Git's submodule and sparse chec
2525

2626
## Supported .gitmodules Variables
2727

28-
fxtag: Specify a specific tag or branch to checkout for a submodule.
28+
fxtag: Specify a specific tag or hash to checkout for a submodule. Branches are not acceptable.
2929
fxrequired: Mark a submodule's checkout behavior, with allowed values:
3030
- ToplevelRequired: Top-level and required (checked out only when this is the Toplevel module).
3131
- ToplevelOptional: Top-level and optional (checked out with --optional flag if this is the Toplevel module).

.lib/git-fleximod/git_fleximod/cli.py

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
from pathlib import Path
22
import argparse, os, sys
3-
from git_fleximod import utils
43

5-
__version__ = "1.0.2"
4+
__version__ = "1.1.1"
5+
66

77
class CustomArgumentParser(argparse.ArgumentParser):
88
def print_help(self, file=None):
@@ -17,13 +17,28 @@ def print_help(self, file=None):
1717
for path in candidate_paths:
1818
if os.path.exists(path):
1919
with open(path) as f:
20-
print( f.read(), file=file)
20+
print(f.read(), file=file)
2121
return
22-
print( "README.md not found.", file=file)
22+
print("README.md not found.", file=file)
23+
2324

2425
def find_root_dir(filename=".gitmodules"):
25-
""" finds the highest directory in tree
26-
which contains a file called filename """
26+
"""
27+
Finds the highest directory in tree which contains a file called filename.
28+
29+
>>> import tempfile, os
30+
>>> cwd = os.getcwd()
31+
>>> with tempfile.TemporaryDirectory() as tmp:
32+
... subdir = Path(tmp) / 'subdir'
33+
... subdir.mkdir()
34+
... f = Path(tmp) / '.gitmodules'
35+
... _ = f.write_text('')
36+
... os.chdir(subdir)
37+
... result = find_root_dir('.gitmodules') == str(tmp)
38+
... os.chdir(cwd)
39+
... result
40+
True
41+
"""
2742
d = Path.cwd()
2843
root = Path(d.root)
2944
dirlist = []
@@ -40,6 +55,7 @@ def find_root_dir(filename=".gitmodules"):
4055
return str(dl)
4156
return None
4257

58+
4359
def get_parser():
4460
description = """
4561
%(prog)s manages checking out groups of gitsubmodules with additional support for Earth System Models
@@ -116,6 +132,13 @@ def get_parser():
116132
"verbosity level each time.",
117133
)
118134

135+
parser.add_argument(
136+
"--no-mods-details",
137+
action="store_true",
138+
default=False,
139+
help="Suppress details on local mods in status output.",
140+
)
141+
119142
parser.add_argument(
120143
"-V",
121144
"--version",

.lib/git-fleximod/git_fleximod/git_fleximod.py

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,27 @@
77

88
import os
99
import shutil
10-
import logging
11-
import textwrap
1210
import asyncio
11+
import logging
12+
from configparser import NoOptionError
1313
from git_fleximod import utils
1414
from git_fleximod import cli
1515
from git_fleximod.gitinterface import GitInterface
1616
from git_fleximod.gitmodules import GitModules
1717
from git_fleximod.submodule import Submodule
1818

19-
# logger variable is global
20-
logger = None
19+
logger = logging.getLogger(__name__)
2120

2221

2322
def fxrequired_allowed_values():
24-
return ["ToplevelRequired", "ToplevelOptional", "AlwaysRequired", "AlwaysOptional", "TopLevelRequired", "TopLevelOptional"]
23+
return [
24+
"ToplevelRequired",
25+
"ToplevelOptional",
26+
"AlwaysRequired",
27+
"AlwaysOptional",
28+
"TopLevelRequired",
29+
"TopLevelOptional",
30+
]
2531

2632

2733
def commandline_arguments(args=None):
@@ -69,6 +75,7 @@ def commandline_arguments(args=None):
6975
options.components,
7076
options.exclude,
7177
options.force,
78+
options.no_mods_details,
7279
action,
7380
)
7481

@@ -151,8 +158,8 @@ def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master
151158

152159
if os.path.isdir(os.path.join(root_dir, path, ".git")):
153160
with utils.pushd(sprep_repo):
154-
if os.path.isdir(os.path.join(topgit,".git")):
155-
shutil.rmtree(os.path.join(topgit,".git"))
161+
if os.path.isdir(os.path.join(topgit, ".git")):
162+
shutil.rmtree(os.path.join(topgit, ".git"))
156163
shutil.move(".git", topgit)
157164
with open(".git", "w") as f:
158165
f.write("gitdir: " + os.path.relpath(topgit))
@@ -167,7 +174,6 @@ def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master
167174
with utils.pushd(sprep_repo):
168175
if os.path.isfile(sparsefile):
169176
shutil.copy(sparsefile, gitsparse)
170-
171177

172178
# Finally checkout the repo
173179
sprepo_git.git_operation("fetch", "origin", "--tags")
@@ -177,7 +183,8 @@ def submodule_sparse_checkout(root_dir, name, url, path, sparsefile, tag="master
177183
rgit.config_set_value(f'submodule "{name}"', "active", "true")
178184
rgit.config_set_value(f'submodule "{name}"', "url", url)
179185

180-
def init_submodule_from_gitmodules(gitmodules, name, root_dir, logger):
186+
187+
def init_submodule_from_gitmodules(gitmodules, name, root_dir, llogger):
181188
path = gitmodules.get(name, "path")
182189
url = gitmodules.get(name, "url")
183190
assert path and url, f"Malformed .gitmodules file {path} {url}"
@@ -187,60 +194,72 @@ def init_submodule_from_gitmodules(gitmodules, name, root_dir, logger):
187194
fxurl = gitmodules.get(name, "fxDONOTUSEurl")
188195
fxsparse = gitmodules.get(name, "fxsparse")
189196
fxrequired = gitmodules.get(name, "fxrequired")
190-
return Submodule(root_dir, name, path, url, fxtag=tag, fxurl=fxurl, fxsparse=fxsparse, fxrequired=fxrequired, logger=logger)
197+
return Submodule(
198+
root_dir,
199+
name,
200+
path,
201+
url,
202+
fxtag=tag,
203+
fxurl=fxurl,
204+
fxsparse=fxsparse,
205+
fxrequired=fxrequired,
206+
logger=llogger,
207+
)
208+
191209

192-
def submodules_status(gitmodules, root_dir, toplevel=False, depth=0):
210+
def submodules_status(
211+
gitmodules, root_dir, toplevel=False, depth=0, no_mods_details=False
212+
):
193213
testfails = 0
194214
localmods = 0
195215
needsupdate = 0
196-
wrapper = textwrap.TextWrapper(initial_indent=' '*(depth*10), width=120,subsequent_indent=' '*(depth*20))
197216
for name in gitmodules.sections():
198217
submod = init_submodule_from_gitmodules(gitmodules, name, root_dir, logger)
199-
200-
result,n,l,t = submod.status()
218+
219+
result, n, l, t = submod.status(depth=depth, no_mods_details=no_mods_details)
201220
if toplevel or not submod.toplevel():
202-
print(wrapper.fill(result))
221+
print(result)
203222
testfails += t
204223
localmods += l
205224
needsupdate += n
206225
subdir = os.path.join(root_dir, submod.path)
207226
if os.path.exists(os.path.join(subdir, ".gitmodules")):
208227
gsubmod = GitModules(logger, confpath=subdir)
209-
t,l,n = submodules_status(gsubmod, subdir, depth=depth+1)
228+
t, l, n = submodules_status(
229+
gsubmod, subdir, depth=depth + 1, no_mods_details=no_mods_details
230+
)
210231
if toplevel or not submod.toplevel():
211232
testfails += t
212233
localmods += l
213234
needsupdate += n
214-
235+
215236
return testfails, localmods, needsupdate
216237

217-
def git_toplevelroot(root_dir, logger):
218-
rgit = GitInterface(root_dir, logger)
238+
239+
def git_toplevelroot(root_dir, llogger):
240+
rgit = GitInterface(root_dir, llogger)
219241
_, superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree")
220242
return superroot
221243

244+
222245
async def submodules_update(gitmodules, root_dir, requiredlist, force):
223246
async def update_submodule(name, requiredlist, force):
224247
submod = init_submodule_from_gitmodules(gitmodules, name, root_dir, logger)
225-
226-
_, needsupdate, localmods, testfails = submod.status()
227248
if not submod.fxrequired:
228249
submod.fxrequired = "AlwaysRequired"
229-
fxrequired = submod.fxrequired
250+
fxrequired = submod.fxrequired
230251
allowedvalues = fxrequired_allowed_values()
231252
assert fxrequired in allowedvalues
232253

233254
superroot = git_toplevelroot(root_dir, logger)
234-
235-
if (
236-
fxrequired
237-
and ((superroot and "Toplevel" in fxrequired)
238-
or fxrequired not in requiredlist)
255+
256+
if fxrequired and (
257+
(superroot and "Toplevel" in fxrequired) or fxrequired not in requiredlist
239258
):
240259
if "Optional" in fxrequired and "Optional" not in requiredlist:
241260
if fxrequired.startswith("Always"):
242261
print(f"Skipping optional component {name:>20}")
243-
return # continue to next submodule
262+
return # continue to next submodule
244263
optional = "AlwaysOptional" in requiredlist
245264

246265
if fxrequired in requiredlist:
@@ -253,11 +272,16 @@ async def update_submodule(name, requiredlist, force):
253272
newrequiredlist = ["AlwaysRequired"]
254273
if optional:
255274
newrequiredlist.append("AlwaysOptional")
256-
await submodules_update(gitsubmodules, repodir, newrequiredlist, force=force)
275+
await submodules_update(
276+
gitsubmodules, repodir, newrequiredlist, force=force
277+
)
257278

258-
tasks = [update_submodule(name, requiredlist, force) for name in gitmodules.sections()]
279+
tasks = [
280+
update_submodule(name, requiredlist, force) for name in gitmodules.sections()
281+
]
259282
await asyncio.gather(*tasks)
260283

284+
261285
def local_mods_output():
262286
text = """\
263287
The submodules labeled with 'M' above are not in a clean state.
@@ -271,7 +295,8 @@ def local_mods_output():
271295
"""
272296
print(text)
273297

274-
def submodules_test(gitmodules, root_dir):
298+
299+
def submodules_test(gitmodules, root_dir, no_mods_details=False):
275300
"""
276301
This function tests the git submodules based on the provided parameters.
277302
@@ -282,12 +307,15 @@ def submodules_test(gitmodules, root_dir):
282307
Parameters:
283308
gitmodules (ConfigParser): The gitmodules configuration.
284309
root_dir (str): The root directory for the git operation.
310+
no_mods_details (bool, optional): If True, suppress details on local mods in status output
285311
286312
Returns:
287313
int: The number of test failures.
288314
"""
289315
# First check that fxtags are present and in sync with submodule hashes
290-
testfails, localmods, needsupdate = submodules_status(gitmodules, root_dir)
316+
testfails, localmods, needsupdate = submodules_status(
317+
gitmodules, root_dir, no_mods_details=no_mods_details
318+
)
291319
print("")
292320
# Then make sure that urls are consistant with fxurls (not forks and not ssh)
293321
# and that sparse checkout files exist
@@ -315,14 +343,17 @@ def main():
315343
includelist,
316344
excludelist,
317345
force,
346+
no_mods_details,
318347
action,
319348
) = commandline_arguments()
320349
# Get a logger for the package
321350
global logger
322351
logger = logging.getLogger(__name__)
323352

324-
logger.info("action is {} root_dir={} file_name={}".format(action, root_dir, file_name))
325-
353+
logger.info(
354+
"action is {} root_dir={} file_name={}".format(action, root_dir, file_name)
355+
)
356+
326357
if not root_dir or not os.path.isfile(os.path.join(root_dir, file_name)):
327358
if root_dir:
328359
file_path = utils.find_upwards(root_dir, file_name)
@@ -352,15 +383,17 @@ def main():
352383
if action == "update":
353384
asyncio.run(submodules_update(gitmodules, root_dir, fxrequired, force))
354385
elif action == "status":
355-
tfails, lmods, updates = submodules_status(gitmodules, root_dir, toplevel=True)
386+
tfails, lmods, updates = submodules_status(
387+
gitmodules, root_dir, toplevel=True, no_mods_details=no_mods_details
388+
)
356389
if tfails + lmods + updates > 0:
357390
print(
358391
f" testfails = {tfails}, local mods = {lmods}, needs updates {updates}\n"
359392
)
360393
if lmods > 0:
361394
local_mods_output()
362395
elif action == "test":
363-
retval = submodules_test(gitmodules, root_dir)
396+
retval = submodules_test(gitmodules, root_dir, no_mods_details=no_mods_details)
364397
else:
365398
utils.fatal_error(f"unrecognized action request {action}")
366399
return retval

0 commit comments

Comments
 (0)