Merge branch 'master' of git://github.com/technomancy/leiningen
This commit is contained in:
commit
d6feadd695
13 changed files with 173 additions and 48 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -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
|
||||
|
|
31
README.md
31
README.md
|
@ -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
|
||||
|
|
6
bin/lein
6
bin/lein
|
@ -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
|
||||
|
|
|
@ -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"]])
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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"]])
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 _
|
||||
|
|
|
@ -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
33
src/leiningen/new.clj
Normal 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))
|
|
@ -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)))
|
||||
|
|
|
@ -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")))
|
||||
|
|
Loading…
Reference in a new issue