Merge branch 'master' of git://github.com/technomancy/leiningen

This commit is contained in:
Dan Larkin 2009-11-21 15:34:38 -05:00
commit d6feadd695
13 changed files with 173 additions and 48 deletions

4
.gitignore vendored
View file

@ -3,4 +3,8 @@ sample/classes/
sample/nomnomnom.jar
classes/
leiningen.jar
leiningen-standalone.jar
pom-generated.xml
pom.xml
Manifest.txt
lein-swank/lein-swank.jar

View file

@ -26,7 +26,9 @@ rather than copying and pasting among each of your projects.
## Installation
Copy bin/lein to a location on your $PATH and run: $ lein self-install
1. Download the script: http://github.com/technomancy/leiningen/raw/stable/bin/lein
2. Place it on your path and chmod it to be executable.
3. Run: <tt>lein self-install</tt>
## Usage
@ -50,7 +52,7 @@ Copy bin/lein to a location on your $PATH and run: $ lein self-install
$ lein help [TASK] # show a list of tasks or help for a given TASK
TODO: new, deploy
$ lein new NAME # generate a new project skeleton
## Configuration
@ -102,6 +104,21 @@ away soon.
**Q:** What about Windows?
**A:** Patches welcome.
## Publishing
If your project is a library and you would like others to be able to
use it as a dependency in their projects, you will need to get it into
a public repository. While it's possible to maintain your own or get
it into Maven central, the easiest way is to publish it at
[Clojars](http://clojars.org), which is a Clojure-specific repository
for open-source code. Once you have created an account there,
publishing is easy:
$ lein pom
$ scp pom.xml $PROJECT.jar clojars@clojars.org:
Once that succeeds it will be available for other projects to depend on.
## Hacking
Working on the Leiningen codebase has a few unique challenges since
@ -111,12 +128,20 @@ necessary:
0. Place bin/lein on your $PATH somewhere.
1. Do a self-install of leiningen (from outside the checkout tree).
2. Place ~/.leiningen.jar in lib.
2. Place ~/.m2/repository/leiningen/leiningen/$VERSION/leiningen-$VERSION.jar in lib.
3. Invoke "lein compile" followed by "lein deps".
4. Remove .leiningen.jar from lib.
5. Invoke "lein uberjar", and place the jar in ~/.leiningen.jar for
future use.
The [mailing list](http://groups.google.com/group/clojure) and the
#leiningen or #clojure channels on Freenode are the best places to
bring up questions or suggestions. Contributions are preferred as
either Github pull requests or using "git format-patch" as described
at http://clojure.org/patches.
Please use standard indentation with no tabs or trailing whitespace.
Leiningen is extensible, you can define new tasks in plugins. Add your
plugin as a dev-dependency of your project, and you'll be able to call
"lein $YOUR_COMMAND". See the lein-swank directory for an example of a

View file

@ -1,7 +1,7 @@
#!/bin/bash
# TODO: this gives us a trailing colon
VERSION=0.5.0
VERSION="1.0.0-SNAPSHOT"
LIBS="$(find -H lib/ -mindepth 2> /dev/null 1 -maxdepth 1 -print0 | tr \\0 \:)"
CLASSPATH="src/:classes/:$LIBS"
LEIN_JAR=$HOME/.m2/repository/leiningen/leiningen/$VERSION/leiningen-$VERSION.jar
@ -9,8 +9,8 @@ LEIN_JAR=$HOME/.m2/repository/leiningen/leiningen/$VERSION/leiningen-$VERSION.ja
# this needs to exist before the JVM is launched apparently
mkdir -p classes
# If we are not running from a checkout
if [ ! -r "bin/lein" ]; then
# If we are not running from a compiled checkout
if [ ! -r "classes/leiningen/core.class" -a ! -r "lib/clojure*jar" ]; then
if [ ! -r "$LEIN_JAR" -a "$1" != "self-install" ]; then
echo "Leiningen is not installed. Please run \"lein self-install\"."
exit 1

View file

@ -1,3 +1,3 @@
(defproject lein-swank "0.5.0-SNAPSHOT"
:dependencies [[leiningen "0.5.0-SNAPSHOT"]
(defproject lein-swank "1.0.0-SNAPSHOT"
:dependencies [[leiningen "1.0.0-SNAPSHOT"]
[org.clojure/swank-clojure "1.0"]])

View file

@ -1,11 +1,8 @@
(ns leiningen.swank
(:use [leiningen.deps :only [deps-if-missing]]))
(:require [swank.swank]))
(defn swank
"Launch swank server for Emacs to connect."
[project & [port]]
(deps-if-missing project)
(let [repl @(ns-resolve 'swank.swank 'start-repl)]
(if port
(repl (Integer. port))
(repl))))
([project port]
(swank.swank/start-repl (Integer. port)))
([project] (swank.swank/start-repl)))

View file

@ -2,13 +2,11 @@
;; defproject form. It can have other code in it as well, including
;; loading other task definitions.
(defproject leiningen "0.5.0"
(defproject leiningen "1.0.0-SNAPSHOT"
:description "A build tool designed not to set your hair on fire."
:main leiningen.core
:dependencies [[org.clojure/clojure "1.1.0-alpha-SNAPSHOT"]
[org.clojure/clojure-contrib "1.0-SNAPSHOT"]
[ant/ant-launcher "1.6.2"]
[org.apache.maven/maven-ant-tasks "2.0.10"]]
;; Wait till this makes it to a public repo.
;; :dev-dependencies [[org.clojure/swank-clojure "1.0"]]
)
:dev-dependencies [[org.clojure/swank-clojure "1.0"]])

View file

@ -11,6 +11,9 @@ unless a list of :namespaces is provided in project.clj."
;; TODO: use a java subprocess in case a different clojure version is needed
(doseq [n (or (:namespaces project)
(find-namespaces-in-dir (file (:root project) "src")))]
(println "Compiling" n)
;; TODO: check to see if bytecode is older than source
(clojure.core/compile n)))
(let [ns-file (str (.replaceAll (name n) "\\." "/"))]
(when (> (.lastModified (file (:root project) "src" (str ns-file ".clj")))
(.lastModified (file (:root project) "classes"
(str ns-file "__init.class"))))
(println "Compiling" n)
(clojure.core/compile n)))))

View file

@ -32,7 +32,9 @@
action-ns (symbol (str "leiningen." command))
_ (require action-ns)
action (ns-resolve action-ns (symbol command))
project (read-project)]
project (if (= command "new") ; only new works without a project.clj
(first args)
(read-project))]
(binding [*compile-path* (or (:compile-path project)
(str (:root project) "/classes/"))]
(apply action project args)

View file

@ -9,10 +9,10 @@
"Install the project and its dependencies into ~/.m2/repository using Maven."
[project & args]
(let [jarfile (jar project)]
(pom project)
(pom project "pom-generated.xml" true)
;; TODO: use maven-ant-tasks InstallTask with in-memory Pom object
(with-sh-dir (:root project)
(try (sh "mvn" "install:install-file" "-DpomFile=pom.xml"
(try (sh "mvn" "install:install-file" "-DpomFile=pom-generated.xml"
(str "-Dfile=" jarfile))
(println "Installed" (:group project) "/" (:name project))
(catch java.io.IOException _

View file

@ -2,7 +2,8 @@
"Create a jar containing the compiled code and original source."
(:require [leiningen.compile :as compile]
[lancet])
(:use [clojure.contrib.duck-streams :only [spit]]))
(:use [leiningen.pom :only [pom]]
[clojure.contrib.duck-streams :only [spit]]))
(defn make-manifest [project]
(doto (str (:root project) "/Manifest.txt")
@ -14,14 +15,19 @@
"Create a $PROJECT.jar file containing the compiled .class files as well as
the source .clj files. If project.clj contains a :main symbol, it will be used
as the main-class for an executable jar."
[project & args]
(compile/compile project)
(let [jar-file (str (:root project) "/" (:name project) ".jar")
filesets [{:dir *compile-path*}
{:dir (str (:root project) "/src")}
{:file (str (:root project) "/project.clj")}]]
;; TODO: support slim, etc
(apply lancet/jar {:jarfile jar-file
:manifest (make-manifest project)}
(map lancet/fileset filesets))
jar-file))
([project jar-name]
(compile/compile project)
(pom project "pom-generated.xml" true)
(let [jar-file (str (:root project) "/" jar-name)
filesets [{:dir *compile-path*}
{:dir (str (:root project) "/src")}
;; TODO: place in META-INF/maven/$groupId/$artifactId/pom.xml
;; TODO: pom.properties
{:file (str (:root project) "/pom-generated.xml")}
{:file (str (:root project) "/project.clj")}]]
;; TODO: support slim, etc
(apply lancet/jar {:jarfile jar-file
:manifest (make-manifest project)}
(map lancet/fileset filesets))
jar-file))
([project] (jar project (str (:name project) ".jar"))))

33
src/leiningen/new.clj Normal file
View file

@ -0,0 +1,33 @@
(ns leiningen.new
"Create a new project skeleton."
(:use [clojure.contrib.duck-streams :only [spit]]
[clojure.contrib.java-utils :only [file]]
[clojure.contrib.str-utils :only [str-join]]))
(defn new [project-name & [args]]
(.mkdirs (file project-name))
(spit (file project-name "project.clj")
(pr-str (list 'defproject (symbol "leiningen") "1.0.0-SNAPSHOT"
:description "FIXME: write"
:dependencies [['org.clojure/clojure
"1.1.0-alpha-SNAPSHOT"]
['org.clojure/clojure-contrib
"1.0-SNAPSHOT"]])))
(doseq [d [(str "src/" project-name) "test" "lib" "classes"]]
(.mkdirs (file project-name d)))
;; maybe keep this somewhere else?
(spit (file project-name "src" (str project-name ".clj"))
(str "(ns " project-name ".core)\n"))
(spit (file project-name ".gitignore")
(str-join "\n" ["pom-generated.xml"
"Manifest.txt"
(str project-name ".jar")]))
(spit (file project-name "lib" ".gitignore") "*")
(spit (file project-name "classes" ".gitignore") "*")
(spit (file project-name "README")
(str-join "\n\n" [(str "# " project-name)
"FIXME: write description"
"## Usage" "FIXME: write"
"## Installation" "FIXME: write"
"## License" "FIXME: write\n"]))
(println "Created new project:" project-name))

View file

@ -1,9 +1,9 @@
(ns leiningen.pom
"Write a pom.xml file to disk for Maven interop."
(:require [lancet])
(:use [clojure.contrib.duck-streams :only [writer]]
(:use [clojure.contrib.duck-streams :only [reader writer]]
[clojure.contrib.java-utils :only [file]])
(:import [org.apache.maven.model Model Parent Dependency Repository]
(:import [org.apache.maven.model Model Parent Dependency Repository Scm]
[org.apache.maven.project MavenProject]
[org.apache.maven.artifact.ant Pom]))
@ -13,6 +13,63 @@
It should not be considered canonical data. For more information see
http://github.com/technomancy/leiningen -->\n")
(defn read-git-ref
"Reads the commit SHA1 for a git ref path."
[git-dir ref-path]
(.trim (slurp (str (file git-dir ref-path)))))
(defn read-git-head
"Reads the value of HEAD and returns a commit SHA1."
[git-dir]
(let [head (.trim (slurp (str (file git-dir "HEAD"))))]
(if-let [ref-path (second (re-find #"ref: (\S+)" head))]
(read-git-ref git-dir ref-path)
head)))
(defn read-git-origin
"Reads the URL for the remote origin repository."
[git-dir]
(with-open [rdr (reader (file git-dir "config"))]
(->> (map #(.trim %) (line-seq rdr))
(drop-while #(not= "[remote \"origin\"]" %))
(next)
(take-while #(not (.startsWith % "[")))
(map #(re-matches #"url\s*=\s*(\S*)\s*" %))
(filter identity)
(first)
(second))))
(defn parse-github-url
"Parses a GitHub URL returning a [username repo] pair."
[url]
(when url
(next
(or
(re-matches #"(?:git@)?github.com:([^/]+)/([^/]+).git" url)
(re-matches #"[^:]+://(?:git@)?github.com/([^/]+)/([^/]+).git" url)))))
(defn github-urls [url]
(when-let [[user repo] (parse-github-url url)]
{:public-clone (str "git://github.com/" user "/" repo ".git")
:dev-clone (str "ssh://git@github.com/" user "/" repo ".git")
:browse (str "http://github.com/" user "/" repo)}))
(defn make-git-scm [git-dir]
(try
(let [origin (read-git-origin git-dir)
head (read-git-head git-dir)
urls (github-urls origin)
scm (Scm.)]
(.setUrl scm (:browse urls))
(.setTag scm head)
(when (:public-clone urls)
(.setConnection scm (str "scm:git:" (:public-clone urls))))
(when (:dev-clone urls)
(.setDeveloperConnection scm (str "scm:git:" (:dev-clone urls))))
scm)
(catch java.io.FileNotFoundException e
nil)))
(defn make-dependency [[dep version]]
(doto (Dependency.)
(.setGroupId (or (namespace dep) (name dep)))
@ -36,10 +93,13 @@
(.setVersion (:version project))
(.setGroupId (:group project))
(.setDescription (:description project)))]
;; TODO: add leiningen as a test-scoped dependency
(doseq [dep (:dependencies project)]
(.addDependency model (make-dependency dep)))
(doseq [repo (concat (:repositories project) default-repos)]
(.addRepository model (make-repository repo)))
(when-let [scm (make-git-scm (file (:root project) ".git"))]
(.setScm model scm))
model))
(defn make-pom [project]
@ -47,13 +107,10 @@
(.setProject lancet/ant-project)
(.setMavenProject (MavenProject. (make-model project)))))
(defn pom [project & [args]]
(let [pom-file (file (:root project) "pom.xml")]
(defn pom [project & [pom-location silently?]]
(let [pom-file (file (:root project) (or pom-location "pom.xml"))]
(with-open [w (writer pom-file)]
(when (or (not (.exists pom-file))
(do (print "pom.xml exists; overwrite? ") (flush)
(re-find #"^y(es)?" (.toLowerCase (read-line)))))
(.writeModel (MavenProject. (make-model project)) w)
(.write w disclaimer)
(println "Wrote pom.xml")))
(.writeModel (MavenProject. (make-model project)) w)
(.write w disclaimer)
(when-not silently? (println "Wrote" (.getName pom-file))))
(.getAbsolutePath pom-file)))

View file

@ -25,4 +25,4 @@ the dependency jars. Suitable for standalone distribution."
:when (.endsWith (.getName dep) ".jar")]
(println "Unpacking" (.getName dep))
(unzip dep *compile-path*))
(jar project))
(jar project (str (:name project) "-standalone.jar")))