deadghost / stevedore

DSL for generating shell scripts using clojure

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

pallet.stevedore

Stevedore is a DSL for generating shell scripts using clojure.

Why?

While there is nothing wrong with normal shell scripting, Stevedore allows the ability to easily interpolate clojure values. As a consequence, we gain the benefits of being able to flexibly parameterize scripts and tailor them to target specific operating systems and their versions.

Installation

Stevedore is distributed as a jar, and is available in the clojars repository.

Installation is with lein or your favourite maven repository aware build tool.

lein project.clj

:dependencies [[com.palletops/stevedore "0.8.0-beta.7"]]

maven pom.xml

<dependencies>
  <dependency>
    <groupId>com.palletops</groupId>
    <artifactId>stevedore</artifactId>
    <version>0.8.0-beta.7</version>
  </dependency>
<dependencies>

<repositories>
  <repository>
    <id>clojars</id>
    <url>http://clojars.org/repo</url>
  </repository>
</repositories>

Examples

Basic Usage

Let's write a basic script; nothing fancy just a plain ole' thing you can easily write in your scripting language of choice. Very static.

(use 'pallet.stevedore)
(require 'pallet.stevedore.bash)

(print
 (with-script-language :pallet.stevedore.bash/bash
   (script
    ("ls" "/some/path")
    (defvar x 1)
    (println @x)
    (defn foo [x] ("ls" @x))
    ("foo" 1)
    (if (= a a)
      (println "Reassuring")
      (println "Ooops"))
    (println "I am" @("whomai")))))

Outputs:

    # form-init7685875326394262653.clj:2
ls /some/path
    # form-init7685875326394262653.clj:3
x=1
    # form-init7685875326394262653.clj:4
echo ${x}
foo() {
x=$1
    # form-init7685875326394262653.clj:5
ls ${x}
}
    # form-init7685875326394262653.clj:6
foo 1
    # form-init7685875326394262653.clj:7
if [ "a" == "a" ]; then echo Reassuring;else echo Ooops;fi
    # form-init7685875326394262653.clj:10
echo I am $(whomai)

Interpolating Clojure

Here is where we start seeing some power. Notice everything escaped with ~ gets evaluated as clojure code before becoming parts of arguments for script.

(print
 (with-script-language :pallet.stevedore.bash/bash
   (let [path "/some/path"]
     (script
      ("ls" ~path)
      ("ls" ~(.replace path "some" "other"))))))

Outputs:

    # form-init7685875326394262653.clj:6
ls /some/path
    # form-init7685875326394262653.clj:7
ls /other/path

Generating Scripts

That's cool, but here's one better. Let's do the same thing as the previous snippet but let's generate the script using a function that takes a path as an argument. This lets us generate a slightly different script with each different argument.

(defn list-path [path]
  "Replaces the \"some\" portion of path argument with the \"other\" string."
  (script
   ("ls" ~path)
   ("ls" ~(.replace path "some" "other"))))

(print (with-script-language :pallet.stevedore.bash/bash
         (list-path "/some/path")))

Outputs:

    # form-init7685875326394262653.clj:7
ls /some/path
    # form-init7685875326394262653.clj:8
ls /other/path
(print (with-script-language :pallet.stevedore.bash/bash
         (list-path "/some/different/path")))

Outputs:

    # form-init7685875326394262653.clj:7
ls /some/different/path
    # form-init7685875326394262653.clj:8
ls /other/different/path

Composing Scripts

Concatenate scripts together using do-script.

(print (with-script-language :pallet.stevedore.bash/bash
		 (do-script
          (list-path "/some/path")
          (list-path "/some/different/path"))))

Outputs:

# form-init7685875326394262653.clj:5
ls /some/path
    # form-init7685875326394262653.clj:6
ls /other/path
# form-init7685875326394262653.clj:5
ls /some/different/path
    # form-init7685875326394262653.clj:6
ls /other/different/path

Chain scripts together with && using chained-script.

(print (with-script-language :pallet.stevedore.bash/bash
		 (chained-script
          (list-path "/some/path")
          (list-path "/some/different/path"))))

Outputs:

# form-init7685875326394262653.clj:4
    # form-init7685875326394262653.clj:5
ls /some/path
    # form-init7685875326394262653.clj:6
ls /other/path && \
# form-init7685875326394262653.clj:5
    # form-init7685875326394262653.clj:5
ls /some/different/path
    # form-init7685875326394262653.clj:6
ls /other/different/path

Chain your scripts and exit if the chain fails using checked-script.

(print (with-script-language :pallet.stevedore.bash/bash
		 (checked-script
          (list-path "/some/path")
          (list-path "/some/different/path"))))

Outputs:

echo '    # form-init7685875326394262653.clj:5
ls /some/path
    # form-init7685875326394262653.clj:6
ls /other/path
...';
{
    # form-init7685875326394262653.clj:5
    # form-init7685875326394262653.clj:5
ls /some/different/path
    # form-init7685875326394262653.clj:6
ls /other/different/path

 } || { echo '#>     # form-init7685875326394262653.clj:5
ls /some/path
    # form-init7685875326394262653.clj:6
ls /other/path
 : FAIL'; exit 1;} >&2 
echo '#>     # form-init7685875326394262653.clj:5
ls /some/path
    # form-init7685875326394262653.clj:6
ls /other/path
 : SUCCESS'

Further Reading

Support

License

Licensed under EPL

Copyright 2010, 2011, 2012, 2013 Hugo Duncan.

About

DSL for generating shell scripts using clojure


Languages

Language:Clojure 92.5%Language:Shell 7.5%