diff --git a/.gitignore b/.gitignore index 198e1b0..ebe23ea 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ docs /.lein-deps-sum *~ /.lein-failures +/.lein-git-deps/ diff --git a/Procfile b/Procfile index 09a6c19..59a9f9a 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -web: lein run +web: lein run -m script.serve diff --git a/project.clj b/project.clj index 09794bb..ac20cb6 100644 --- a/project.clj +++ b/project.clj @@ -10,13 +10,15 @@ :dev-dependencies [[jline "0.9.94"] [marginalia "0.7.0-SNAPSHOT"] [lein-marginalia "0.7.0-SNAPSHOT"]] - :repositories {"oss-sonatype-staging" - "https://oss.sonatype.org/content/groups/staging/"} - :main ^:skip-aot one.sample.launchpad + :git-dependencies [["https://github.com/clojure/clojurescript.git" + "329708bdd0f039241b187bc639836d9997d8fbd4"] + ["https://github.com/levand/domina.git" + "c0eb06f677e0f9f72537682e3c702dd27b03e2e4"]] + :repl-init one.sample.repl :source-path "src/app/clj" - :extra-classpath-dirs ["lib/clojurescript/src/clj" - "lib/clojurescript/src/cljs" - "lib/domina/src/cljs" + :extra-classpath-dirs [".lein-git-deps/clojurescript/src/clj" + ".lein-git-deps/clojurescript/src/cljs" + ".lein-git-deps/domina/src/cljs" "src/app/cljs" "src/app/cljs-macros" "src/lib/clj" diff --git a/script/build b/script/build index 19455de..93d4d26 100755 --- a/script/build +++ b/script/build @@ -1,24 +1,3 @@ #!/bin/bash -set -e - -cd `dirname $0`/.. - -mkdir -p out - -echo "Creating out/public..." -cp -a public out/ -rm out/public/index.html -rm out/public/design.html -rm -rf out/public/javascripts/* - -source script/setup_classpath.sh - -echo "Create advanced compiled JavaScript..." -java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \ -"(use 'one.tools) - (use 'one.sample.config) - (build-project config)" - -echo "[build complete]" - +lein run -m script.build diff --git a/script/build.cmd b/script/build.cmd new file mode 100644 index 0000000..3d96111 --- /dev/null +++ b/script/build.cmd @@ -0,0 +1 @@ +lein run -m script.build diff --git a/script/cljs-repl b/script/cljs-repl deleted file mode 100755 index daa1f3a..0000000 --- a/script/cljs-repl +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -cd `dirname $0`/.. - -source script/setup_classpath.sh - -java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \ -"(use '[one.sample.dev-server :only (run-server cljs-repl)]) - (use '[clojure.java.browse :only (browse-url)]) - (run-server) - (future (Thread/sleep 3000) (browse-url \"http://localhost:8080/development\")) - (cljs-repl)" --repl - diff --git a/script/deps b/script/deps deleted file mode 100755 index c67677d..0000000 --- a/script/deps +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash - -set -e - -cd `dirname $0`/.. - -echo "Getting lein deps..." -lein deps - -cd lib - -git clone https://github.com/levand/domina.git - -git clone https://github.com/clojure/clojurescript.git - -cd domina -git checkout -b clojurescript-one-lib c0eb06f677e0f9f72537682e3c702dd27b03e2e4 - -cd ../clojurescript -git checkout -b clojurescript-one-lib 329708bdd0f039241b187bc639836d9997d8fbd4 - -echo "[Deps Completed]" diff --git a/script/repl b/script/repl new file mode 100644 index 0000000..bf221d8 --- /dev/null +++ b/script/repl @@ -0,0 +1,6 @@ +#!/bin/bash + +# This is here for convention. Many Emacs users have their +# inferior-lisp-program set to script/repl. + +lein repl diff --git a/script/run b/script/run deleted file mode 100755 index 2e462bd..0000000 --- a/script/run +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -cd `dirname $0`/.. - -source script/setup_classpath.sh - -java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \ -"(use 'one.sample.dev-server) - (run-server) - (println \"The application is being served from localhost:8080\")" --repl diff --git a/script/serve b/script/serve new file mode 100755 index 0000000..738ba8b --- /dev/null +++ b/script/serve @@ -0,0 +1,6 @@ +#!/bin/bash + +# Start the production server which will serve the contents of +# out/public and the API for the sample application. + +lein run -m script.serve diff --git a/script/setup_classpath.sh b/script/setup_classpath.sh deleted file mode 100644 index a3df95d..0000000 --- a/script/setup_classpath.sh +++ /dev/null @@ -1,8 +0,0 @@ -CLOJURESCRIPT_HOME=lib/clojurescript - -CLJSC_CP='lib/*:lib/dev/*' -for next in 'src/clj' 'src/cljs' 'test/cljs'; do - CLJSC_CP=${CLJSC_CP}:$CLOJURESCRIPT_HOME'/'$next -done - -CLJSC_CP=$CLJSC_CP':lib/domina/src/cljs:src/app/clj:src/app/cljs:src/app/cljs-macros:src/lib/clj:src/lib/cljs:test:templates' diff --git a/script/test b/script/test deleted file mode 100755 index 87b7630..0000000 --- a/script/test +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -cd `dirname $0`/.. - -source script/setup_classpath.sh - -java -server -cp $CLJSC_CP jline.ConsoleRunner clojure.main -e \ -"(use 'one.sample.test.suite) - (run-all) - (shutdown-agents)" diff --git a/src/app/clj/one/sample/launchpad.clj b/src/app/clj/one/sample/launchpad.clj deleted file mode 100644 index 0696d48..0000000 --- a/src/app/clj/one/sample/launchpad.clj +++ /dev/null @@ -1,39 +0,0 @@ -(ns one.sample.launchpad - "The starting namespace for the project. This is the namespace that - users will land in when they start a Clojure REPL. It exists both to - process commands passed on the command line (such as 'build') and to - provide convenience functions like 'go'." - (:use [clojure.repl]) - (:require [one.sample.config :as config] - [one.tools :as tools] - [one.sample.dev-server :as dev] - [one.sample.prod-server :as prod] - [clojure.java.io :as io] - [clojure.java.browse :as browse])) - -(defn go - "Start a browser-connected REPL and launch a browser to talk to it." - [] - (dev/run-server) - (future (Thread/sleep 3000) - (browse/browse-url "http://localhost:8080/development")) - (tools/cljs-repl)) - -(defmulti command (fn [args] (first args))) - -(defmethod command "build" [_] - (println "Creating out/public...") - (.mkdir (io/file "out")) - (tools/copy-recursive-into "public" "out") - (tools/delete "out/public/index.html" - "out/public/design.html" - "out/public/javascripts") - (.mkdir (io/file "out/public/javascripts")) - (println "Create advanced compiled JavaScript...") - (tools/build-project config/config)) - -(defmethod command nil [_] - (prod/run-server)) - -(defn -main [& args] - (command args)) \ No newline at end of file diff --git a/src/app/clj/one/sample/repl.clj b/src/app/clj/one/sample/repl.clj new file mode 100644 index 0000000..3c6cb37 --- /dev/null +++ b/src/app/clj/one/sample/repl.clj @@ -0,0 +1,30 @@ +(ns one.sample.repl + "The starting namespace for the project. This is the namespace that + users will land in when they start a Clojure REPL. It exists both to + process commands passed on the command line (such as 'build') and to + provide convenience functions like 'go'." + (:use [clojure.repl]) + (:require [one.tools :as tools] + [one.sample.dev-server :as dev] + [clojure.java.browse :as browse])) + +(defn go + "Start a browser-connected REPL and launch a browser to talk to it." + [] + (dev/run-server) + (future (Thread/sleep 3000) + (browse/browse-url "http://localhost:8080/development")) + (tools/cljs-repl)) + +(defn dev-server + "Start the development server and open the host application in the + default browser." + [] + (dev/run-server) + (future (Thread/sleep 3000) + (browse/browse-url "http://localhost:8080"))) + +(println) +(println "Type (go) to launch the development server and setup a browser-connected REPL.") +(println "Type (dev-server) to launch only the development server.") +(println) diff --git a/src/app/clj/script/build.clj b/src/app/clj/script/build.clj new file mode 100644 index 0000000..20c568c --- /dev/null +++ b/src/app/clj/script/build.clj @@ -0,0 +1,15 @@ +(ns script.build + (:require [clojure.java.io :as io] + [one.tools :as tools] + [one.sample.config :as config])) + +(defn -main [] + (println "Creating out/public...") + (.mkdir (io/file "out")) + (tools/copy-recursive-into "public" "out") + (tools/delete "out/public/index.html" + "out/public/design.html" + "out/public/javascripts") + (.mkdir (io/file "out/public/javascripts")) + (println "Create advanced compiled JavaScript...") + (tools/build-project config/config)) diff --git a/src/app/clj/script/serve.clj b/src/app/clj/script/serve.clj new file mode 100644 index 0000000..864aabe --- /dev/null +++ b/src/app/clj/script/serve.clj @@ -0,0 +1,5 @@ +(ns script.serve + (:require [one.sample.prod-server :as prod])) + +(defn -main [] + (prod/run-server)) diff --git a/src/leiningen/bootstrap.clj b/src/leiningen/bootstrap.clj new file mode 100644 index 0000000..73b60fb --- /dev/null +++ b/src/leiningen/bootstrap.clj @@ -0,0 +1,9 @@ +(ns leiningen.bootstrap + (:require leiningen.deps + leiningen.git-deps)) + +(defn bootstrap + "Bootstrap the project by running lein deps and lein git-deps." + [project] + (leiningen.deps/deps project) + (leiningen.git-deps/git-deps project)) diff --git a/src/leiningen/git_deps.clj b/src/leiningen/git_deps.clj new file mode 100644 index 0000000..91ea7be --- /dev/null +++ b/src/leiningen/git_deps.clj @@ -0,0 +1,108 @@ +(ns leiningen.git-deps + "How this works: It clones projects into .lein-git-deps/. + If the directory already exists, it does a git pull and git checkout." + (:require [clojure.java.shell :as sh] + [clojure.java.io :as io] + [clojure.string :as string])) + +(def ^:private git-deps-dir ".lein-git-deps") + +(defn- directory-exists? + "Return true if the specified directory exists." + [dir] + (.isDirectory (io/file dir))) + +(defn- penultimate + "Return the second-to-last element of a collection." + [coll] + (last (butlast coll))) + +(defn- default-clone-dir + "Given a git URL, return the directory it would clone into by default." + [uri] + (string/join "." (-> uri + (string/split #"/") + (last) + (string/split #"\.") + butlast))) + +(defn- exec + "Run a command, throwing an exception if it fails, returning the +result as with clojure.java.shell/sh." + [& args] + (let [{:keys [exit out err] :as result} (apply sh/sh args)] + (if (zero? exit) + result + (throw + (Exception. + (format "Command %s failed with exit code %s\n%s\n%s" + (apply str (interpose " " args)) + exit + out + err)))))) + +(defn- git-clone + "Clone the git repository at url into dir-name while working in +directory working-dir." + [url dir-name working-dir] + (apply exec (remove nil? ["git" "clone" url (str dir-name) :dir working-dir]))) + +(defn- git-checkout + "Check out the specified commit in dir" + [commit dir] + (println "Running git checkout " commit " in " (str dir)) + (exec "git" "checkout" commit :dir dir)) + +(defn- detached-head? + "Return true if the git repository in dir has HEAD detached." + [dir] + (let [{out :out} (exec "git" "branch" "--color=never" :dir dir) + lines (string/split-lines out) + current-branch (first (filter #(.startsWith % "*") lines))] + (when-not current-branch + (throw (Exception. "Unable to determine current branch"))) + (= current-branch "* (no branch)"))) + +(defn- git-pull + "Run 'git-pull' in directory dir, but only if we're on a branch. If +HEAD is detached, we only do a fetch, not a full pull." + [dir] + (println "Running git pull on " (str dir)) + (if (detached-head? dir) + (do + (println "Not on a branch, so fetching instead of pulling.") + (exec "git" "fetch" :dir dir)) + (exec "git" "pull" :dir dir))) + +(defn git-deps + "A leiningen task that will pull dependencies in via git. + +Dependencies should be listed in project.clj under the +:git-dependencies key in one of these three forms: + +:git-dependencies [;; First form: just a URL. +[\"https://github.com/foo/bar.git\"] + +;; Second form: A URL and a ref, which can be anything +;; you can specify for 'git checkout', like a commit ide +;; or a branch name. +[\"https://github.com/foo/baz.git\" + \"329708b\"] + +;; Third form: A URL, a commit, and a map +[\"https://github.com/foo/quux.git\" + \"some-branch\" + {:dir \"alternate-directory\"}]]" +[project] +(when-not (directory-exists? git-deps-dir) + (.mkdir (io/file git-deps-dir))) +(doseq [dep (:git-dependencies project)] + (println "Setting up dependency for " dep) + (let [[dep-url commit {clone-dir-name :dir}] dep + commit (or commit "master") + clone-dir-name (or clone-dir-name (default-clone-dir dep-url)) + clone-dir (io/file git-deps-dir clone-dir-name)] + (if (directory-exists? clone-dir) + (git-pull clone-dir) + (git-clone dep-url clone-dir-name git-deps-dir)) + (git-checkout commit clone-dir))))