I think it might be smarter to start from first principles on this stuff,
and attempt to create a toolset that would allow us to make RH/Debian/etc.
compatible packages from all maven builds, including Maven itself an Maven's
dependencies.

FWIW, I've looked at some of the patches you posted, and there's no way some
of that stuff would ever make it into the codebase. For one thing, it uses
singletons and system properties...we're moving away from system properties,
because they don't lend themselves to embedding very well, and I suspect the
singleton might be dangerous to embedded environments too, since it can have
implications for thread safety and can lack parallel configurability.

I have to say that I'm deeply troubled by other parts of the patch set where
artifact versions are hard-coded to 2.0.4 (dropping the version
information).

Finally, the bootstrap changes are based on a bootstrap that we're not using
anymore...that may or may not be a good thing, but it is what it is.

I guess I'd like to understand in detail what your requirements are, and
start talking from there, rather than being in the position of critiquing
something that may be a less-than-ideal solution produced as a proof of
concept.

Let's start with: What are the requirements?

Regards,

John

On 12/6/06, Deepak Bhole <[EMAIL PROTECTED]> wrote:

On Wed, 2006-12-06 at 11:57 -0500, Jason van Zyl wrote:
> On 6 Dec 06, at 11:38 AM 6 Dec 06, Carl Trieloff wrote:
>
> > I have spoken with a few committers over IRC, ApacheCon etc about
> > this so here it comes. Some of us would like to include maven into
> > Fedora distributions. There are two components to this, one
> > technical and the other process similar to the Apache incubator
> > process in that you need a sponsor, need to pass review etc...
> >
>
> To be frank, I'm not so sure this would be a good thing for Maven
> users. It's not terribly hard to install and here are some of the
> problems I see:
>
> 1. Who is going to maintain this? It seems rather complicated when we
> have something that works pretty easily.
>

The patch's goals are twofold.
1: Ensure full offline mode (the -o switch still allows maven to try and
   check for plugin updates and what not in valid repositories)
2: Ensure that projects can build against a single version of a
   dependency, rather than multiple.

> 2. On Redhat would Maven be laid out differently then our stock
> install? For documentation, and learning purposes having Maven be
> laid out different and work differently on different platforms is not
> something I would like to see. It will just make it more difficult
> for Maven users. Maven does more then Java but we are about platform
> neutrality and having something that works in a specific way on
> Redhat that doesn't translate to working on OS/X is not a good thing.
>

Maven is laid out differently by the rpm. However, this has nothing to
do with Red Hat specifically. The RPM adheres to the Filesystem
Heirarchy Standard (FHS), which a reference for install locations for
*nix systems: http://www.pathname.com/fhs/

> 3. What about multiple versions? This would make Maven bound to the
> OS which is also not a good thing. I have often run into many problem
> where multiple versions are not allowed. I run 4 different versions
> of Maven and using RPMs here would make this difficult.
>

As I mentioned in point 2 in #1 above, this is actually one of the
things we want (optionally, ofcourse). JPackage (used by Red Hat, Suse,
Mandriva, etc.) currently does not support multiple version
installations of a package in parallel. Due to this limitation, we need
a maven there that can work with 1 version of each package.

> I would be extremely hesitant to make this the standard offering for
> Maven users on Redhat. I would be hesitant to off anything that did
> not work in a standard way, or as much of a standard way as possible,
> between all platforms. I do not see this as a great benefit to Maven
> users.
>

All of the stuff done by the patch is optional, and not enabled by
default. Everything is controlled by properties (e.g.
-Dmaven2.ignore.versions has to be there for maven to ignore versions
and go with 1 version per dependency, and so on). Whatever the patch
does, is intended to be used on a range of distributions, not just in
Fedora.

Cheers,
Deepak

> Jason.
>
> >
> > A few of us have been working on working out all the issues to meet
> > the Fedora and Linux distro guidelines. Thanks to Deepak he has
> > worked out most of this and has created a set of patches for maven
> > in addition to identifying the work that needs to be done each time
> > an update needs to be included into Fedora. It would be ideal if we
> > could create a maven target with each release that met these
> > guidelines and work in a Linux distro build environment. Once we
> > get through the technical, Deepak,  and I can help drive the
> > process with Fedora.
> >
> > Please take a look, Deepak can JIRA all the patches and a few of us
> > can
> > help with this.
> >
> > Regards
> > Carl, Deepak
> >
> >
> > The following provided by Deepak
> >
> >
> > Since there is a strict "must build offline" requirement, the
> > maven2 rpm
> > is designed to build completely disconnected from the Internet. To
> > this
> > end, the rpm is self-contained -- it contains poms, necessary jars for
> > bootstrapping, etc.
> >
> > Here is where all the maven2 sources are (explanation of source
> > files is
> > at the end):
> > http://people.redhat.com/dbhole/maven/
> >
> > It is strongly recommended that whoever plans to help out with this,
> > reads the maven2-jpp-readme.html file, as it gives a brief idea as to
> > how the mapping system works. Changes from maven2-jpprepolayout.patch
> > (or their equivalent), and new files
> > maven2-JPackageRepositoryLayout.java and maven2-
> > MavenJPackageDepmap.java
> > (or their equivalent) need to go upstream in order to make everything
> > work with jpackage smoothly.
> >
> > In order to put maven2 into Fedora, here are the brief set of steps
> > for
> > all dependencies, and maven itself:
> >
> > 1. Get rpm from jpackage. Check if it is set to build natively.
> > If not,
> >     Build it, run it through spec-gcj-convert (file attached), verify
> >     new spec, rebuild it, make sure it conforms to Fedora guidelines
> >     for everything except the release number and all, that should be
> >     jpackage specific. Then upload this to jpackage.
> >   If it is:
> >     Do nothing
> >
> > 2. Then, use the latest spec from jpackage after doing #1, update the
> >   release to match fc guidelines, merge changelog, build into Fedora.
> >
> >
> > A brief explanation what the files are for:
> > -> m2_jar_repo.tar.gz - An archive of certain jar files needed for
> >   building (some maven2 dependencies need maven2 to build -- so maven2
> >   has a bootstrap mode where pre-built jars are used. Once such a
> > maven
> >   is built, it is then used to build all dependencies, and then maven
> >   is re-built in non-bootstrap mode against those dependencies)
> > -> m2_pom_repo.tar.gz - An archive of all the pom files needed for
> >   building
> > -> maven2-addjdom-depmap.xml - Adds a jdom dependency to maven.
> > jdom is
> >   used by the jpp mapping system
> > -> maven2-addjdomtobootstrappath.patch - Adds jdom to the bootstrap
> >   classpath (see above note)
> > -> maven2-buildallplugins.patch - Patch to enable plugins that maven
> >   disables by default (we always build as much as possible in our
> >   packages).
> > -> maven2-disable-itests.patch - Patch to disable integration
> > tests. The
> >   tests take a long time to run, so this patch is used to disable them
> >   (unless the --with itests switch is given)
> > -> maven2-empty-dep.jar/pom - Certain jars in maven repositories are
> >   monolithic and not needed when building against JPackage packages.
> >   e.g. velocity-dep, which contains all of velocity's dependencies.
> >   Since the jpp mapping system can only map one-to-one, we need to
> >   maven dependencies such as velocity-dep to something... that
> >   something is this empty-dep which contains no classes.
> > -> maven2-enable-unbuilt-modules.patch - As with plugins, we also
> > try to
> >   build as many modules as possible. This patch enables it such
> >   modules.
> > -> maven2-it-jppfixes.patch - This patch was originally needed with
> > the
> >   old rpm. In theory, only the first chunk of patch should be needed
> >   (to enable the -s switch), but I am not certain -- it needs to be
> >   investigated.
> > -> maven2-JPackageRepositoryLayout.java -> The "JPackage layout".
> > In the
> >   Jpackage layout, a file location is $groupId/$artifactId.jar with
> > any
> >   "."'s in the groupId converted to "/"'s first. *This file, or an
> >   equivalent needs to go upstream*
> > -> maven2-jpp-readme.html - A readme for how packages should be built
> >   around this maven.
> > -> maven2-jpprepolayout.patch - The most critical component of all.
> > This
> >   patch wires in usage of the jpackage repository. Additionally, it
> >   also ensures that maven will not go online -- not for dependencies,
> >   not for checking plugin updates, not for anything. It also adds
> > the    jpackage repository (/usr/share/maven2/repository) to the
> > default
> >   list. *The changes in here are the ones that need to go upstream*
> > -> maven2-jpp-script - The init script for jpackage building. It is a
> >   wrapper around the mvn script -- it calls mvn with certain
> > properties
> >   that causes maven to behave in an offline manner,
> >   use /usr/share/maven2/repository, etc.
> > -> maven2-MavenJPackageDepmap.java - A helper package that loads the
> >   dependency map, provides the value based on key requested, etc.
> > *This
> >   file, or an equivalent needs to go upstream*
> > -> maven2-maven-site-plugin.tar.gz - The maven-site-plugin. The
> > version
> >   in the plugins tarball cannot build against the new doxia.
> > -> maven2-model-v3.tar.gz - The model v3 class
> > -> maven2-plugins-060420-src.tar.gz - The plugins tarball.
> > See .spec to
> >   see how it was generated
> > -> maven2-plugins-plexus151.patch - Disabled a code stub that causes
> >   build to fail against plexus-utils 1.5.1+
> > -> maven2-run-it-tests.sh - Script to run integration tests
> > -> maven2-script - The mvn wrapper script
> > -> maven2-settings.xml - I don't think this is used anymore..
> > -> maven2-src.tar.gz - The maven2-2.0.4 source tarball from svn.
> >
> >
> > Cheers,
> > Deepak
> >
> >
> > #!/usr/bin/env python
> >
> > # spec-convert-gcj
> > # ================
> > #
> > # Create a JPackage spec file that contains GCJ support from a
> > JPackage
> > # SRPM and its corresponding RPMs.  spec-convert-gcj uses the
> > binary RPMs
> > # to determine each sub-package's list of jar files.
> > #
> > # Example:
> > #   spec-convert-gcj ~/rpmbuild/SRPMS/bsh-*1.3.0-6jpp* ~/rpmbuild/
> > RPMS/noarch/bsh-*1.3.0-6jpp*
> >
> > import sys
> > import os
> > import warnings
> >
> > class Error(Exception):
> >     pass
> >
> > # parsing state
> > state = "PREAMBLE"
> >
> > partList = [ "PREAMBLE",
> >              "%package",
> >              "%prep",
> >              "%build",
> >              "%install",
> >              "%check",
> >              "%clean",
> >              "%preun",
> >              "%postun",
> >              "%pre",
> >              "%post",
> >              "%files",
> >              "%changelog",
> >              "%description",
> >              "%triggerpostun",
> >              "%triggerun",
> >              "%triggerin",
> >              "%trigger",
> >              "%verifyscript",
> >              "END" ]
> >
> > packages = {}
> >
> > macroizedpackagenames = {}
> >
> > currentpackage = None
> >
> > doneuptofiles = False
> >
> > mainpackageempty = False
> >
> > NAME = "spec-convert-gcj"
> > VERSION = "1.1"
> >
> > class Package:
> >     name = ""
> >     jarfilenames = []
> >     postdone = False
> >     postundone = False
> >
> >     def __init__(self, name, jarfilenames):
> >         self.name = name
> >         self.jarfilenames = jarfilenames
> >
> >     def contains_jars(self):
> >         return len(self.jarfilenames) != 0
> >
> >     def get_name(self):
> >         return self.name
> >
> >     def get_jar_file_names(self):
> >         return self.jarfilenames
> >
> >     def set_post_done(self):
> >         self.postdone = True
> >
> >     def get_post_done(self):
> >         return self.postdone
> >
> >     def set_postun_done(self):
> >         self.postundone = True
> >
> >     def get_postun_done(self):
> >         return self.postdone
> >
> >     def __str__(self):
> >         return self.name
> >
> > def get_package_name(rpmfilename):
> >     rpmoutput = os.popen("rpm --queryformat %{name} -qp " +
> > rpmfilename)
> >     packagename = rpmoutput.read()
> >     status = rpmoutput.close()
> >     if status is not None or packagename == "":
> >         raise Error, "spec file name lookup failed"
> >     else:
> >         print "spec file name lookup passed"
> >     return packagename
> >
> > def extract_files(rpmfilename, filenamepattern):
> >     status = os.system("rpm2cpio " + rpmfilename + " | cpio -id " +
> > filenamepattern)
> >     if status > 0:
> >         raise Error, "%s exited with code %d" % ("cpio", status)
> >     elif status < 0:
> >         raise Error, "%s killed by signal %d" % ("cpio", -status)
> >     else:
> >         print "rpm2cpio passed"
> >
> > def get_jar_file_names_callback(jarfilenames, dirname, fnames):
> >     for fname in fnames:
> >         if fname.endswith(".jar") \
> >                and os.path.isfile(os.path.join(dirname, fname)) \
> >                and not os.path.islink(os.path.join(dirname, fname)):
> >             jarfilenames.append(fname)
> >             os.remove(os.path.join(dirname, fname))
> >
> > def note_package(rpmfilename):
> >     global packages
> >     unmacroizedpackagename = get_package_name(rpmfilename)
> >     if unmacroizedpackagename != mainpackagename + "-debuginfo":
> >         if unmacroizedpackagename == mainpackagename:
> >             packagename = mainpackagename
> >         else:
> >             packagename = macroizedpackagenames
> > [unmacroizedpackagename]
> >         jarfilenames = []
> >         extract_files(rpmfilename, "*.jar")
> >         os.path.walk(".", get_jar_file_names_callback, jarfilenames)
> >         packages[packagename] = Package(packagename, jarfilenames)
> >
> > def filter_preamble(line):
> >     if line.lower().startswith("buildarch:"):
> >         if line.lower().split()[1] == "noarch":
> >             add_buildarch(line)
> >         else:
> >             outputspecfile.write(line)
> >     else:
> >         outputspecfile.write(line)
> >
> > def add_buildarch(line):
> >     outputspecfile.write("%if ! %{gcj_support}\n")
> >     outputspecfile.write(line)
> >     outputspecfile.write("%endif\n")
> >
> > def add_requires():
> >     outputspecfile.write("%if %{gcj_support}\n")
> >     outputspecfile.write("BuildRequires:\t\tjava-gcj-compat-devel\n")
> >     outputspecfile.write("Requires(post):\t\tjava-gcj-compat\n")
> >     outputspecfile.write("Requires(postun):\tjava-gcj-compat\n")
> >     outputspecfile.write("%endif\n")
> >     outputspecfile.write("\n")
> >
> > def add_aot_compile_rpm():
> >     outputspecfile.write("%if %{gcj_support}\n")
> >     outputspecfile.write("%{_bindir}/aot-compile-rpm\n")
> >     outputspecfile.write("%endif\n")
> >     outputspecfile.write("\n")
> >
> > def add_so_and_db_files():
> >     outputspecfile.write("%if %{gcj_support}\n")
> >     outputspecfile.write("%dir %attr(-,root,root) %{_libdir}/gcj/%
> > {name}\n")
> >     for jarfilename in currentpackage.get_jar_file_names():
> >         outputspecfile.write("%attr(-,root,root) %{_libdir}/gcj/%
> > {name}/" + jarfilename + ".*\n")
> >     outputspecfile.write("%endif\n")
> >     outputspecfile.write("\n")
> >
> > def add_rebuild_gcj_db():
> >     outputspecfile.write("%if %{gcj_support}\n")
> >     add_rebuild_gcj_db_no_condition()
> >     outputspecfile.write("%endif\n")
> >     outputspecfile.write("\n")
> >
> > def add_rebuild_gcj_db_no_condition():
> >     outputspecfile.write("if [ -x %{_bindir}/rebuild-gcj-db ]\n")
> >     outputspecfile.write("then\n")
> >     outputspecfile.write("  %{_bindir}/rebuild-gcj-db\n")
> >     outputspecfile.write("fi\n")
> >
> > def add_name(name):
> >     if name.startswith(mainpackagename):
> >     if name != mainpackagename:
> >             outputspecfile.write(" " + name.replace(mainpackagename +
> > "-", "", 1))
> >     else:
> >     # full name
> >     outputspecfile.write(" -n " + name)
> >     outputspecfile.write("\n")
> >
> > def add_post(name):
> >     outputspecfile.write("%if %{gcj_support}\n")
> >     outputspecfile.write("%post")
> >     add_name(name)
> >     add_rebuild_gcj_db_no_condition()
> >     outputspecfile.write("%endif\n")
> >     outputspecfile.write("\n")
> >
> > def add_postun(name):
> >     outputspecfile.write("%if %{gcj_support}\n")
> >     outputspecfile.write("%postun")
> >     add_name(name)
> >     add_rebuild_gcj_db_no_condition()
> >     outputspecfile.write("%endif\n")
> >     outputspecfile.write("\n")
> >
> > def add_before_part(state):
> >     global doneuptofiles
> >
> >     if state == "%files":
> >         if doneuptofiles == False:
> >             for packagename in packages:
> >                 package = packages[packagename]
> >                 if package.contains_jars():
> >                     if not package.get_post_done():
> >                         add_post(package.get_name())
> >                     if not package.get_postun_done():
> >                         add_postun(package.get_name())
> >             doneuptofiles = True
> >
> > def add_to_part(state):
> >     if state == "PREAMBLE":
> >         if currentpackage is not None \
> >                and currentpackage.contains_jars():
> >             add_requires()
> >     if state == "%package":
> >         if currentpackage is not None \
> >                and currentpackage.contains_jars():
> >             add_requires()
> >     elif state == "%install":
> >         add_aot_compile_rpm()
> >     elif state == "%files":
> >         if currentpackage is not None \
> >                and currentpackage.contains_jars():
> >             add_so_and_db_files()
> >     elif state == "%post":
> >         if currentpackage is not None \
> >                and currentpackage.contains_jars():
> >             add_rebuild_gcj_db()
> >             currentpackage.set_post_done()
> >     elif state == "%postun":
> >         if currentpackage is not None \
> >                and currentpackage.contains_jars():
> >             add_rebuild_gcj_db()
> >             currentpackage.set_postun_done()
> >
> > def set_currentpackage(line):
> >     global currentpackage
> >
> >     fields = line.split()
> >     if len(fields) == 1:
> >     if not mainpackageempty:
> >             try:
> >                 currentpackage = packages[mainpackagename]
> >             except KeyError, e:
> >             pass
> >     else:
> >             currentpackage = None
> >     else:
> >     if fields[1] == "-n":
> >             # full name specified
> >             try:
> >             currentpackage = packages[fields[2]]
> >             except KeyError, e:
> >             pass
> >     else:
> >             try:
> >             currentpackage = packages[mainpackagename + "-" +
fields[1]]
> >             except KeyError, e:
> >             pass
> >
> > def set_macroized_package_names():
> >     global macroizedpackagenames
> >
> >     packagelines = os.popen("cat " + specfilename + " | grep '^%
> > package'")
> >     packagenames = os.popen("rpm -q --specfile --queryformat='%
> > {name}\n' " + specfilename + " | grep -v " + mainpackagename + "-
> > debuginfo")
> >
> >     packageline = packagelines.readline()
> >     # skip main package name
> >     packagename = packagenames.readline()
> >     packagename = packagenames.readline()
> >
> >     if packagename != "":
> >         while packageline != "":
> >             fields = packageline.split()
> >             if len(fields) == 2:
> >                 macroizedpackagenames[packagename.strip()] =
> > mainpackagename + "-" + fields[1]
> >             else:
> >                 if len(fields) == 3:
> >                     macroizedpackagenames[packagename.strip()] =
> > fields[2]
> >             packageline = packagelines.readline()
> >             packagename = packagenames.readline()
> >
> >     packagelines.close()
> >     packagenames.close()
> >
> >     if packageline != "" or packagename !="":
> >         raise Error, "number of Name: and %package lines does not
> > match number of names returned by spec file query"
> >     else:
> >         print "macroized package names creation passed"
> >
> >     print "map of unmacroized names to macroized names:"
> >     print macroizedpackagenames
> >
> > def next_state(line):
> >     global state
> >     if line == "":
> >         add_to_part(state)
> >         state = "END"
> >         return
> >     for part in partList:
> >         if line.startswith(part):
> >             add_to_part(state)
> >             state = part
> >             add_before_part(state)
> >             set_currentpackage(line)
> >
> > def print_version():
> >     print NAME, VERSION
> >     sys.exit(0)
> >
> > def print_usage():
> >     print "Usage: " + NAME + " SRPM RPMS"
> >     print "Create a JPackage spec file that contains GCJ support
> > from a JPackage"
> >     print "SRPM and its corresponding RPMs.  " + NAME + " uses the
> > binary RPMs"
> >     print "to determine each sub-package's list of jar files."
> >     print ""
> >     print "Example:"
> >     print "  " + NAME + " ~/rpmbuild/SRPMS/bsh-*1.3.0-6jpp* ~/
> > rpmbuild/RPMS/noarch/bsh-*1.3.0-6jpp*"
> >     sys.exit(0)
> >
> > if __name__ == "__main__":
> >     try:
> >
> >         options = sys.argv[1:]
> >
> >         if len(options) == 0:
> >             print NAME + ": no input files"
> >             print_usage()
> >
> >         origdir = os.getcwd()
> >
> >         # find SRPM within arguments
> >         srpmfilename = ""
> >         rpmfilenames = []
> >         for option in options:
> >             if option.endswith(".src.rpm"):
> >                 if srpmfilename != "":
> >                     raise Error, "more than one SRPM specified"
> >                 else:
> >                     srpmfilename = os.path.join(origdir, option)
> >             elif option.endswith(".rpm"):
> >                 rpmfilenames.append(os.path.join(origdir, option))
> >             elif option == "--version":
> >                 print_version()
> >             elif option == "--help":
> >                 print_usage()
> >
> >         warnings.filterwarnings("ignore", message="tmpnam is a
> > potential security risk to your program")
> >         tmpdir = os.path.basename(os.tmpnam())
> >         os.mkdir(tmpdir)
> >         os.chdir(tmpdir)
> >
> >         # get spec file name: assumes that the spec file is called
> >         # %{name}.spec
> >         print "processing: " + srpmfilename
> >         mainpackagename = get_package_name(srpmfilename)
> >         specfilename = mainpackagename + ".spec"
> >
> >         # extract spec file
> >         print "extracting spec file: " + specfilename
> >         extract_files(srpmfilename, specfilename)
> >
> >         # check for existing gcj support
> >         checkconverted = os.popen("grep gcj_support " + specfilename)
> >     checksupport = checkconverted.readline()
> >         if checksupport != "":
> >             raise Error, "these rpms already support gcj"
> >         status = checkconverted.close()
> >         if status is None:
> >             raise Error, "failed to close grep pipe"
> >         else:
> >             print "no gcj support detected"
> >
> >         # calculate unmacroized name-to-macroized name mapping
> >         set_macroized_package_names()
> >
> >         for rpmfilename in rpmfilenames:
> >             note_package(rpmfilename)
> >
> >         # open spec file for reading
> >         specfile = open(specfilename, 'r')
> >
> >         # open output spec file for writing
> >         outputspecfile = open(os.path.join(origdir, mainpackagename
> > + "-gcj.spec"), 'w')
> >
> >         # check if there is a main package or only sub-packages
> >         if mainpackagename in packages:
> >             currentpackage = packages[mainpackagename]
> >         else:
> >         mainpackageempty = True
> >
> >         print "main package:", currentpackage
> >
> >         line = specfile.readline()
> >         next_state(line)
> >
> >         # skip license block
> >         while line.startswith("#"):
> >             outputspecfile.write(line)
> >             line = specfile.readline()
> >
> >     outputspecfile.write("\n%define gcj_support %{?_with_gcj_support:
> > 1}%{!?_with_gcj_support:%{?_without_gcj_support:0}%{!?
> > _without_gcj_support:%{?_gcj_support:%{_gcj_support}}%{!?
> > _gcj_support:0}}}\n")
> >
> >         while line != "":
> >             if state == "PREAMBLE":
> >                 filter_preamble(line)
> >             else:
> >                 outputspecfile.write(line)
> >
> >             line = specfile.readline()
> >             next_state(line)
> >
> >         outputspecfile.close()
> >
> >         os.chdir(origdir)
> >
> >     except Error, e:
> >         print >> sys.stderr, "%s: error: %s" % (
> >             os.path.basename(sys.argv[0]), e)
> >         sys.exit(1)
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Reply via email to