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