Skip to content

Commit bad56c1

Browse files
committed
[GR-8893] Add command to flatten multi-release sources.
PullRequest: mx/601
2 parents c37936d + 90ddca9 commit bad56c1

File tree

1 file changed

+96
-10
lines changed

1 file changed

+96
-10
lines changed

mx.py

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
from collections import Callable, OrderedDict, namedtuple, deque
6363
from datetime import datetime
6464
from threading import Thread
65-
from argparse import ArgumentParser, REMAINDER, Namespace, FileType, HelpFormatter
65+
from argparse import ArgumentParser, REMAINDER, Namespace, FileType, HelpFormatter, ArgumentTypeError
6666
from os.path import join, basename, dirname, exists, isabs, expandvars, isdir
6767
from tempfile import mkdtemp
6868
import fnmatch
@@ -1304,11 +1304,9 @@ def addSrcFromDir(srcDir, archivePrefix=''):
13041304
archivePrefix = p.archive_prefix()
13051305
if mrjVersion is not None:
13061306
try:
1307-
mrjVersion = int(mrjVersion)
1308-
if mrjVersion < 9:
1309-
raise ValueError()
1310-
except ValueError:
1311-
abort("Value of 'multiReleaseJarVersion' attribute should be an integer greater or equal to 9: " + str(mrjVersion), context=p)
1307+
mrjVersion = _parse_multireleasejar_version(mrjVersion)
1308+
except ArgumentTypeError as e:
1309+
abort(str(e), context=p)
13121310
archivePrefix = 'META-INF/versions/{}/'.format(mrjVersion)
13131311
if 'Multi-Release: true' not in manifestEntries:
13141312
manifestEntries.append('Multi-Release: true')
@@ -2311,6 +2309,47 @@ def _eclipseinit(self, files=None, libFiles=None, absolutePaths=False):
23112309
"""
23122310
_eclipseinit_project(self, files=files, libFiles=libFiles, absolutePaths=absolutePaths)
23132311

2312+
def get_multireleasesources_flatten_map(self):
2313+
"""
2314+
Gets a map from the versioned source directories in this project to the
2315+
non-versioned source directories they [preside over](https://docs.oracle.com/javase/9/docs/specs/jar/jar.html).
2316+
"""
2317+
if not hasattr(self, 'multiReleaseJarVersion'):
2318+
return {}
2319+
def _find_version_base_project():
2320+
extended_packages = self.extended_java_packages()
2321+
if not extended_packages:
2322+
abort('Project with a multiReleaseJarVersion attribute must have sources in a package defined by project without multiReleaseJarVersion attribute', context=self)
2323+
base_project = None
2324+
base_package = None
2325+
for extended_package in extended_packages:
2326+
for p in projects():
2327+
if self != p and p.isJavaProject() and not hasattr(p, 'multiReleaseJarVersion'):
2328+
if extended_package in p.defined_java_packages():
2329+
if base_project is None:
2330+
base_project = p
2331+
base_package = extended_package
2332+
else:
2333+
if base_project != p:
2334+
abort('Multi-release jar versioned project {} must extend packages from exactly one project but extends {} from {} and {} from {}'.format(self, extended_package, p, base_project, base_package))
2335+
if not base_project:
2336+
abort('Multi-release jar versioned project {} must extend package(s) from another project'.format(self))
2337+
return base_project
2338+
2339+
base = _find_version_base_project()
2340+
flatten_map = {}
2341+
self_packages = self.defined_java_packages() | self.extended_java_packages()
2342+
for package in self_packages:
2343+
relative_package_src_dir = package.replace('.', os.sep)
2344+
for self_package_src_dir in [join(s, relative_package_src_dir) for s in self.source_dirs()]:
2345+
if exists(self_package_src_dir):
2346+
assert len(base.source_dirs()) != 0, '{} has no source directories!'.format(base)
2347+
for base_package_src_dir in [join(s, relative_package_src_dir) for s in base.source_dirs()]:
2348+
if exists(base_package_src_dir) or not flatten_map.has_key(self_package_src_dir):
2349+
flatten_map[self_package_src_dir] = base_package_src_dir
2350+
assert len(self_packages) == len(flatten_map), 'could not find sources for all packages in ' + self.name
2351+
return flatten_map
2352+
23142353
def getBuildTask(self, args):
23152354
requiredCompliance = self.javaCompliance
23162355
if not requiredCompliance.isExactBound and hasattr(args, 'javac_crosscompile') and args.javac_crosscompile:
@@ -11338,10 +11377,11 @@ def findfiles_by_vc(pyfiles):
1133811377
if f.endswith('.py'):
1133911378
pyfile = join(root, f)
1134011379
pyfiles.append(pyfile)
11341-
if args.walk:
11342-
findfiles_by_walk(pyfiles)
1134311380
else:
11344-
findfiles_by_vc(pyfiles)
11381+
if args.walk:
11382+
findfiles_by_walk(pyfiles)
11383+
else:
11384+
findfiles_by_vc(pyfiles)
1134511385

1134611386
env = os.environ.copy()
1134711387

@@ -11920,6 +11960,51 @@ def help_(args):
1192011960
doc = doc.format(*fmtArgs)
1192111961
print 'mx {0} {1}\n\n{2}\n'.format(name, usage, doc)
1192211962

11963+
def _parse_multireleasejar_version(value):
11964+
try:
11965+
mrjVersion = int(value)
11966+
if mrjVersion < 9:
11967+
raise ArgumentTypeError('multi-release jar version ({}) must be greater than 8'.format(value))
11968+
return mrjVersion
11969+
except ValueError:
11970+
raise ArgumentTypeError('multi-release jar version ({}) must be an int value greater than 8'.format(value))
11971+
11972+
def flattenMultiReleaseSources(args):
11973+
"""print map for flattening multi-release sources
11974+
11975+
Prints space separated (versioned_dir, base_dir) pairs where versioned_dir contains versioned sources
11976+
for a multi-release jar and base_dir contains the corresponding non-versioned (or base versioned)
11977+
sources.
11978+
"""
11979+
parser = ArgumentParser(prog='mx flattenmultireleasesources')
11980+
parser.add_argument('-c', '--commands', action='store_true', help='format the output as a series of commands to copy '\
11981+
'the versioned sources to the location of the non-versioned sources')
11982+
parser.add_argument('version', type=_parse_multireleasejar_version, help='major version of the Java release for which flattened sources will be produced')
11983+
11984+
args = parser.parse_args(args)
11985+
versions = {}
11986+
for p in projects():
11987+
if p.isJavaProject() and hasattr(p, 'multiReleaseJarVersion'):
11988+
version = _parse_multireleasejar_version(getattr(p, 'multiReleaseJarVersion'))
11989+
if version <= args.version:
11990+
versions.setdefault(version, []).append(p.get_multireleasesources_flatten_map())
11991+
else:
11992+
# Ignore overlays for versions higher than the one requested
11993+
pass
11994+
11995+
# Process versioned overlays in ascending order such that higher versions
11996+
# override lower versions. This corresponds with how versioned classes in
11997+
# multi-release jars are resolved.
11998+
for version, maps in sorted(versions.items()):
11999+
for flatten_map in maps:
12000+
for src_dir, dst_dir in flatten_map.iteritems():
12001+
if not args.commands:
12002+
print src_dir, dst_dir
12003+
else:
12004+
if not exists(dst_dir):
12005+
print 'mkdir -p {}'.format(dst_dir)
12006+
print 'cp {}{}* {}'.format(src_dir, os.sep, dst_dir)
12007+
1192312008
def projectgraph(args, suite=None):
1192412009
"""create graph for project structure ("mx projectgraph | dot -Tpdf -oprojects.pdf" or "mx projectgraph --igv")"""
1192512010

@@ -15941,6 +16026,7 @@ def list_commands(l):
1594116026
'eclipseinit': [eclipseinit_cli, ''],
1594216027
'envs': [show_envs, '[options]'],
1594316028
'exportlibs': [exportlibs, ''],
16029+
'flattenmultireleasesources' : [flattenMultiReleaseSources, 'version'],
1594416030
'findbugs': [mx_findbugs.findbugs, ''],
1594516031
'findclass': [findclass, ''],
1594616032
'fsckprojects': [fsckprojects, ''],
@@ -16801,7 +16887,7 @@ def alarm_handler(signum, frame):
1680116887

1680216888

1680316889
# The comment after VersionSpec should be changed in a random manner for every bump to force merge conflicts!
16804-
version = VersionSpec("5.146") # always tasks
16890+
version = VersionSpec("5.147.0") # GR-8893
1680516891

1680616892
currentUmask = None
1680716893
_mx_start_datetime = datetime.utcnow()

0 commit comments

Comments
 (0)