diff --git a/.gitignore b/.gitignore index e69de29..fde128f 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1 @@ +/v3.2.7_2.10.tar.gz diff --git a/climbing-nemesis.py b/climbing-nemesis.py new file mode 100644 index 0000000..4bdd5ca --- /dev/null +++ b/climbing-nemesis.py @@ -0,0 +1,244 @@ +#!/usr/bin/env python + +# Copyright 2013, 2014 Red Hat, Inc., and William C. Benton +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import xml.etree.ElementTree as ET +import argparse +import StringIO +import re +import subprocess +import logging + +from os.path import exists as pathexists +from os.path import realpath +from os.path import join as pathjoin +from os import makedirs +from os import symlink +from os import remove as rmfile +from shutil import copyfile + +class Artifact(object): + def __init__(self, a, g, v): + self.artifact = a + self.group = g + self.version = v + + @classmethod + def fromCoords(k, coords): + g,a,v = coords.split(":") + return k(a, g, v) + + @classmethod + def fromSubtree(k, t, ns): + a = t.find("./%sartifactId" % ns).text + g = t.find("./%sgroupId" % ns).text + v = t.find("./%sversion" % ns).text + return k(a, g, v) + + def contains(self, substrings): + for s in substrings: + if s in self.artifact or s in self.group: + cn_debug("ignoring %r because it contains %s" % (self, s)) + return True + if len(substrings) > 0: + cn_debug("not ignoring %r; looked for %r" % (self, substrings)) + return False + + def __repr__(self): + return "%s:%s:%s" % (self.group, self.artifact, self.version) + +class DummyPOM(object): + def __init__(self, groupID=None, artifactID=None, version=None): + self.groupID = groupID + self.artifactID = artifactID + self.version = version + self.deps = [] + +def interestingDep(dt, namespace): + if len(dt.findall("./%soptional" % namespace)) != 0: + cn_debug("ignoring optional dep %r" % Artifact.fromSubtree(dt, namespace)) + return False + if [e for e in dt.findall("./%sscope" % namespace) if e.text == "test"] != []: + cn_debug("ignoring test dep %r" % Artifact.fromSubtree(dt, namespace)) + return False + return True + +class POM(object): + def __init__(self, filename, suppliedGroupID=None, suppliedArtifactID=None, ignored_deps=[], override=None, extra_deps=[]): + self.filename = filename + self.sGroupID = suppliedGroupID + self.sArtifactID = suppliedArtifactID + self.logger = logging.getLogger("com.freevariable.climbing-nemesis") + self.deps = [] + self.ignored_deps = ignored_deps + self.extra_deps = extra_deps + cn_debug("POM: extra_deps is %r" % extra_deps) + self._parsePom() + self.claimedGroup, self.claimedArtifact = override is not None and override or (self.groupID, self.artifactID) + + def _parsePom(self): + tree = ET.parse(self.filename) + project = tree.getroot() + self.logger.info("parsing POM %s", self.filename) + self.logger.debug("project tag is '%s'", project.tag) + tagmatch = re.match("[{](.*)[}].*", project.tag) + namespace = tagmatch and "{%s}" % tagmatch.groups()[0] or "" + self.logger.debug("looking for '%s'", ("./%sgroupId" % namespace)) + groupIDtag = project.find("./%sgroupId" % namespace) + if groupIDtag is None: + groupIDtag = project.find("./%sparent/%sgroupId" % (namespace,namespace)) + + versiontag = project.find("./%sversion" % namespace) + if versiontag is None: + versiontag = project.find("./%sparent/%sversion" % (namespace,namespace)) + self.logger.debug("group ID tag is '%s'", groupIDtag) + self.groupID = groupIDtag.text + self.artifactID = project.find("./%sartifactId" % namespace).text + self.version = versiontag.text + depTrees = project.findall(".//%sdependencies/%sdependency" % (namespace, namespace)) + alldeps = [Artifact.fromSubtree(depTree, namespace) for depTree in depTrees if interestingDep(depTree, namespace)] + alldeps = [dep for dep in alldeps if not (dep.group == self.groupID and dep.artifact == self.artifactID)] + self.deps = [dep for dep in alldeps if not dep.contains(self.ignored_deps)] + [Artifact.fromCoords(xtra) for xtra in self.extra_deps] + jarmatch = re.match(".*JPP-(.*).pom", self.filename) + self.jarname = (jarmatch and jarmatch.groups()[0] or None) + +def cn_debug(*args): + logging.getLogger("com.freevariable.climbing-nemesis").debug(*args) + +def cn_info(*args): + logging.getLogger("com.freevariable.climbing-nemesis").info(*args) + +def resolveArtifact(group, artifact, pomfile=None, kind="jar", ignored_deps=[], override=None, extra_deps=[]): + # XXX: some error checking would be the responsible thing to do here + cn_debug("rA: extra_deps is %r" % extra_deps) + if pomfile is None: + try: + if getFedoraRelease() > 19: + [pom] = subprocess.check_output(["xmvn-resolve", "%s:%s:pom:%s" % (group, artifact, kind)]).split() + else: + [pom] = subprocess.check_output(["xmvn-resolve", "%s:%s:%s" % (group, artifact, kind)]).split() + return POM(pom, ignored_deps=ignored_deps, override=override, extra_deps=extra_deps) + except: + return DummyPOM(group, artifact) + else: + return POM(pomfile, ignored_deps=ignored_deps, override=override, extra_deps=extra_deps) + +def resolveArtifacts(identifiers): + coords = ["%s:%s:jar" % (group, artifact) for (group, artifact) in identifiers] + poms = subprocess.check_output(["xmvn-resolve"] + coords).split() + return [POM(pom) for pom in poms] + +def resolveJar(group, artifact): + [jar] = subprocess.check_output(["xmvn-resolve", "%s:%s:jar:jar" % (group, artifact)]).split() + return jar + +def makeIvyXmlTree(org, module, revision, status="release", meta={}, deps=[]): + ivy_module = ET.Element("ivy-module", {"version":"1.0", "xmlns:e":"http://ant.apache.org/ivy/extra"}) + info = ET.SubElement(ivy_module, "info", dict({"organisation":org, "module":module, "revision":revision, "status":status}.items() + meta.items())) + info.text = " " # ensure a close tag + confs = ET.SubElement(ivy_module, "configurations") + for conf in ["default", "provided", "test"]: + ET.SubElement(confs, "conf", {"name":conf}) + pubs = ET.SubElement(ivy_module, "publications") + ET.SubElement(pubs, "artifact", {"name":module, "type":"jar"}) + if len(deps) > 0: + deptree = ET.SubElement(ivy_module, "dependencies") + for dep in deps: + ET.SubElement(deptree, "dependency", {"org":dep.group, "name":dep.artifact, "rev":dep.version}) + return ET.ElementTree(ivy_module) + +def writeIvyXml(org, module, revision, status="release", fileobj=None, meta={}, deps=[]): + # XXX: handle deps! + if fileobj is None: + fileobj = StringIO.StringIO() + tree = makeIvyXmlTree(org, module, revision, status, meta=meta, deps=deps) + tree.write(fileobj, xml_declaration=True) + return fileobj + +def ivyXmlAsString(org, module, revision, status, meta={}, deps=[]): + return writeIvyXml(org, module, revision, status, meta=meta, deps=deps).getvalue() + +def placeArtifact(artifact_file, repo_dirname, org, module, revision, status="release", meta={}, deps=[], supplied_ivy_file=None, scala=None, override=None, override_dir_only=False): + if scala is not None: + module = module + "_%s" % scala + jarmodule = module + if override is not None: + org, module = override + if not override_dir_only: + jarmodule = module + repo_dir = realpath(repo_dirname) + artifact_dir = pathjoin(*[repo_dir] + [org] + [module, revision]) + ivyxml_path = pathjoin(artifact_dir, "ivy.xml") + artifact_repo_path = pathjoin(artifact_dir, "%s-%s.jar" % (jarmodule, revision)) + + if not pathexists(artifact_dir): + makedirs(artifact_dir) + + ivyxml_file = open(ivyxml_path, "w") + if supplied_ivy_file is None: + writeIvyXml(org, module, revision, status, ivyxml_file, meta=meta, deps=deps) + else: + copyfile(supplied_ivy_file, ivyxml_path) + + if pathexists(artifact_repo_path): + rmfile(artifact_repo_path) + + symlink(artifact_file, artifact_repo_path) + +def getFedoraRelease(): + cmd = "rpm -q --qf %{version} fedora-release" + return int(subprocess.check_output(cmd.split())) + +def main(): + parser = argparse.ArgumentParser(description="Place a locally-installed artifact in a custom local Ivy repository; get metadata from Maven") + parser.add_argument("group", metavar="GROUP", type=str, help="name of group") + parser.add_argument("artifact", metavar="ARTIFACT", type=str, help="name of artifact") + parser.add_argument("repodir", metavar="REPO", type=str, help="location for local repo") + parser.add_argument("--version", metavar="VERSION", type=str, help="version to advertise this artifact as, overriding Maven metadata") + parser.add_argument("--meta", metavar="K=V", type=str, help="extra metadata to store in ivy.xml", action='append') + parser.add_argument("--jarfile", metavar="JAR", type=str, help="local jar file (use instead of POM metadata") + parser.add_argument("--pomfile", metavar="POM", type=str, help="local pom file (use instead of xmvn-resolved one") + parser.add_argument("--log", metavar="LEVEL", type=str, help="logging level") + parser.add_argument("--ivyfile", metavar="IVY", type=str, help="supplied Ivy file (use instead of POM metadata)") + parser.add_argument("--scala", metavar="VERSION", type=str, help="encode given scala version in artifact name") + parser.add_argument("--ignore", metavar="STR", type=str, help="ignore dependencies whose artifact or group contains str", action='append') + parser.add_argument("--override", metavar="ORG:NAME", type=str, help="override organization and/or artifact name") + parser.add_argument("--override-dir-only", action='store_true', help="override organization and/or artifact name") + parser.add_argument("--extra-dep", metavar="ORG:NAME:VERSION", action='append', help="add the given dependencya") + args = parser.parse_args() + + if args.log is not None: + logging.basicConfig(level=getattr(logging, args.log.upper())) + + override = args.override and args.override.split(":") or None + cn_debug("cl: args.extra_dep is %r" % args.extra_dep) + extra_deps = args.extra_dep is not None and args.extra_dep or [] + + pom = resolveArtifact(args.group, args.artifact, args.pomfile, "jar", ignored_deps=(args.ignore or []), override=((not args.override_dir_only) and override or None), extra_deps=extra_deps) + + if args.jarfile is None: + jarfile = resolveJar(pom.groupID or args.group, pom.artifactID or args.artifact) + else: + jarfile = args.jarfile + + version = (args.version or pom.version) + + meta = dict([kv.split("=") for kv in (args.meta or [])]) + cn_debug("meta is %r" % meta) + + placeArtifact(jarfile, args.repodir, pom.groupID, pom.artifactID, version, meta=meta, deps=pom.deps, supplied_ivy_file=args.ivyfile, scala=args.scala, override=override, override_dir_only=args.override_dir_only) + +if __name__ == "__main__": + main() diff --git a/json4s.spec b/json4s.spec new file mode 100644 index 0000000..31bdcc5 --- /dev/null +++ b/json4s.spec @@ -0,0 +1,183 @@ +%global json4s_version 3.2.7 +%global scala_version 2.10 + +%global remap_version_to_installed() sed -i -e 's/"%{1}" %% "%{2}" %% "[^"]*"/"%{1}" %% "%{2}" %% "'$(rpm -q --qf "%%%%{version}" $(rpm -q --whatprovides "mvn(%{1}:%{2})" ))'"/g' %{3} + +# we don't want scalaz support atm +%global want_scalaz 0 + +Name: json4s +Version: %{json4s_version} +Release: 1%{?dist} +Summary: Common AST for Scala JSON parsers + +License: ASL 2.0 +URL: https://github.com/json4s/json4s +Source0: https://github.com/json4s/json4s/archive/v%{json4s_version}_%{scala_version}.tar.gz +Source1: https://raw.github.com/willb/climbing-nemesis/master/climbing-nemesis.py + +BuildArch: noarch +BuildRequires: sbt +BuildRequires: scala +BuildRequires: python +BuildRequires: maven-local +BuildRequires: javapackages-tools +Requires: javapackages-tools +Requires: scala + +Requires: mvn(com.thoughtworks.paranamer:paranamer) +Requires: mvn(org.scala-lang:scalap) +Requires: mvn(com.fasterxml.jackson.core:jackson-databind) +Requires: mvn(com.fasterxml.jackson.core:jackson-core) +Requires: mvn(com.fasterxml.jackson.core:jackson-annotations) +Requires: mvn(joda-time:joda-time) +Requires: mvn(org.joda:joda-convert) + +BuildRequires: mvn(com.thoughtworks.paranamer:paranamer) +BuildRequires: mvn(org.scala-lang:scalap) +BuildRequires: mvn(com.fasterxml.jackson.core:jackson-databind) +BuildRequires: mvn(com.fasterxml.jackson.core:jackson-core) +BuildRequires: mvn(com.fasterxml.jackson.core:jackson-annotations) +BuildRequires: mvn(joda-time:joda-time) +BuildRequires: mvn(org.joda:joda-convert) + +%description + +json4s is a common AST for Scala JSON parsers. + +%package javadoc +Summary: Javadoc for %{name} + +%description javadoc +Javadoc for %{name}. + +%prep +%setup -q -n %{name}-%{version}_%{scala_version} + +# eliminate lift codeOB +rm -rf native-lift + +# work around buildinfo absence +sed -i -e 's/BuildInfo.organization/"org.json4s"/' jackson/src/main/scala/org/json4s/jackson/Json4sScalaModule.scala +sed -i -e 's/BuildInfo.name/"json4s"/' jackson/src/main/scala/org/json4s/jackson/Json4sScalaModule.scala +sed -i -e 's/BuildInfo.version/"%{version}"/' jackson/src/main/scala/org/json4s/jackson/Json4sScalaModule.scala + +sed -i -e 's/2[.]10[.][012]/2.10.3/g' project/* + +sed -i -e 's/0[.]13[.]0/0.13.1/g' project/build.properties || echo sbt.version=0.13.1 > project/build.properties + +sed -i -e '/lift build/d' project/Dependencies.scala +sed -i -e '/def crossMapped/,+1d' project/Dependencies.scala + +%remap_version_to_installed com.fasterxml.jackson.core jackson-databind project/Dependencies.scala + +# not used in Fedora +sed -i -e '/net.liftweb/d' project/Dependencies.scala + +# only needed by liftweb +sed -i -e '/commons-codec/d' project/Dependencies.scala + +# only needed by examples and benchmarks +sed -i -e '/jackson-module-scala/d' project/Dependencies.scala + +sed -i -e 's/cross crossMapped.*//' project/Dependencies.scala + +sed -i -i '/com.typesafe/d' project/build.scala + +sed -i -e '/lazy val examples = Project/,/lazy val.*= Project/{/.*/d}' project/build.scala +sed -i -e '/^[/][/].*/d' project/build.scala + +%if %{want_scalaz} == 0 +sed -i -e '/scalaz/d' project/Dependencies.scala +sed -i -e 's/scalazExt,//' project/build.scala +sed -i -e '/lazy val scalazExt/,/dependsOn/d' project/build.scala +%endif + +for target in json4sTests benchmark mongo ; do +sed -i -e '/lazy val '$target'/,/dependsOn/d' project/build.scala +sed -i -e 's/'$target',//' project/build.scala +done + +sed -i -e 's/[+][+] buildInfoSettings//' project/build.scala +sed -i -e '/buildInfo/d' project/build.scala +sed -i -e '/sbtbuildinfo/d' project/build.scala + +# munge publishSettings +sed -i 's/^\(.*val publishSetting =.*\)$/PUBLISH_SETTING_HERE\n\1/' project/build.scala +sed -i '/val publishSetting =/,/^[[:space:]]*[}][[:space:]]*$/d' project/build.scala +sed -i 's|PUBLISH_SETTING_HERE|val publishSetting = publishTo <<= (version) { version: String =>\nval cwd = java.lang.System.getProperty("user.dir")\nSome(Resolver.file("published", file("published"))(Resolver.ivyStylePatterns) ivys s"$cwd/published/[organization]/[module]/[revision]/ivy.xml" artifacts s"$cwd/published/[organization]/[module]/[revision]/[artifact]-[revision].[ext]")\n}|' project/build.scala + +rm -f project/plugins.sbt + +cp -r /usr/share/sbt/ivy-local . +mkdir boot + +cp %{SOURCE1} . + +chmod 755 climbing-nemesis.py + +./climbing-nemesis.py com.thoughtworks.paranamer paranamer ivy-local --version 2.6 +./climbing-nemesis.py org.scala-lang scalap ivy-local --version 2.10.3 +./climbing-nemesis.py com.fasterxml.jackson.core jackson-databind ivy-local --ignore maven-scm-provider-gitexe +./climbing-nemesis.py com.fasterxml.jackson.core jackson-core ivy-local --ignore maven-scm-provider-gitexe +./climbing-nemesis.py com.fasterxml.jackson.core jackson-annotations ivy-local --ignore maven-scm-provider-gitexe +./climbing-nemesis.py joda-time joda-time ivy-local --version 2.3 +./climbing-nemesis.py org.joda joda-convert ivy-local --version 1.6 + +%build + +export SBT_BOOT_DIR=boot +export SBT_IVY_DIR=ivy-local + +sbt package "set publishTo in Global := Some(Resolver.file(\"published\", file(\"published\"))(Resolver.ivyStylePatterns) ivys \"$(pwd)/published/[organization]/[module]/[revision]/ivy.xml\" artifacts \"$(pwd)/published/[organization]/[module]/[revision]/[artifact]-[revision].[ext]\")" publish makePom + +# XXX: this is a hack; we seem to get correct metadata but bogus JARs +# from "sbt publish" for some reason +for f in $(find published -name \*.jar ) ; do + find . -ipath \*target\* -and -name $(basename $f) -exec cp '{}' $f \; +done + +%install +mkdir -p %{buildroot}/%{_javadir}/%{name} +mkdir -p %{buildroot}/%{_mavenpomdir} + +mkdir -p %{buildroot}/%{_javadocdir}/%{name} +for apidir in $(find . -name api -type d) ; do + pushd $apidir + cp -rp . %{buildroot}/%{_javadocdir}/%{name} + popd +done + +for jar in $(find published -name \*.jar | grep -v %{name}_%{scala_version}-%{version}.jar) ; do + install -m 644 $jar %{buildroot}/%{_javadir}/%{name}/$(echo $jar | cut -f5 -d/ | cut -f1 -d_).jar +done + +declare -a shortnames + +for pom in $(find published -name \*.pom | grep -v %{name}_%{scala_version}-%{version}.pom ) ; do + shortname=$(echo $pom | cut -f5 -d/ | cut -f1 -d_) + echo installing POM $pom to %{_mavenpomdir}/JPP.%{name}-${shortname}.pom + install -pm 644 $pom %{buildroot}/%{_mavenpomdir}/JPP.%{name}-${shortname}.pom + echo %{_mavenpomdir}/JPP.%{name}-${shortname}.pom >> .rpm_pomfiles + shortnames=( "${shortnames[@]}" $shortname ) +done + +for sub in ${shortnames[@]} ; do + echo running add_maven_depmap JPP.%{name}-${sub}.pom %{name}/${sub}.jar + %add_maven_depmap JPP.%{name}-${sub}.pom %{name}/${sub}.jar +done + +%files -f .mfiles +%dir %{_javadir}/%{name} + +%doc LICENSE README.md + +%files javadoc +%{_javadocdir}/%{name} +%doc LICENSE + + +%changelog + +* Wed Feb 19 2014 William Benton - 3.2.7-1 +- initial package diff --git a/sources b/sources index e69de29..7459299 100644 --- a/sources +++ b/sources @@ -0,0 +1 @@ +aa40abfc8dde47ae7e69305a87639733 v3.2.7_2.10.tar.gz