Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
  • 2 commits
  • 2 files changed
  • 0 comments
  • 1 contributor

Showing 2 changed files with 135 additions and 24 deletions. Show diff stats Hide diff stats

  1. +58 24 README.md
  2. +77 0 src/main/clojure/clojure/tools/namespace/move.clj
82 README.md
Source Rendered
@@ -11,38 +11,45 @@ It has nothing to do with Leiningen, Maven, JAR files, or
11 11 repositories.
12 12
13 13
  14 +
14 15 Releases and Dependency Information
15   -========================================
  16 +----------------------------------------
16 17
17   -* [Latest stable release is 0.2.0](https://github.com/clojure/tools.namespace/tree/tools.namespace-0.2.0)
  18 +* [Latest stable release is 0.2.1](https://github.com/clojure/tools.namespace/tree/tools.namespace-0.2.1)
18 19
19 20 * [All Released Versions](http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22tools.namespace%22)
20 21
21 22 [Leiningen](https://github.com/technomancy/leiningen) dependency information:
22 23
23   - [org.clojure/tools.namespace "0.2.0"]
  24 + [org.clojure/tools.namespace "0.2.1"]
24 25
25 26 [Maven](http://maven.apache.org/) dependency information:
26 27
27 28 <dependency>
28 29 <groupId>org.clojure</groupId>
29 30 <artifactId>tools.namespace</artifactId>
30   - <version>0.2.0-SNAPSHOT</version>
  31 + <version>0.2.1</version>
31 32 </dependency>
32 33
33 34
34   -Development Snapshots
35   ----------------------
  35 +### Development Snapshots ###
36 36
37   -* Git master branch is **0.2.1-SNAPSHOT**
  37 +* Git master branch is at **0.2.2-SNAPSHOT**
38 38
39 39 * [Development Snapshot Versions](https://oss.sonatype.org/content/groups/public/org/clojure/tools.namespace/)
40 40
41   -* [Instructions for Development Snapshot Repositories](http://dev.clojure.org/display/doc/Maven+Settings+and+Repositories)
  41 +Leiningen information for development snapshots:
42 42
  43 + :dependencies [[org.clojure/tools.namespace "0.2.2-SNAPSHOT"]]
  44 + :repositories {"sonatype-oss-public"
  45 + "https://oss.sonatype.org/content/groups/public/"}
  46 +
  47 +See also [Maven Settings and Repositories](http://dev.clojure.org/display/doc/Maven+Settings+and+Repositories) on dev.clojure.org.
43 48
44   -Usage
45   -========================================
  49 +
  50 +
  51 +Overview
  52 +----------------------------------------
46 53
47 54 [API Documentation](http://clojure.github.com/tools.namespace/)
48 55
@@ -75,6 +82,10 @@ see below. c.t.n.repl is built out of smaller parts:
75 82 You can recombine these parts in other ways, but c.t.n.repl is the
76 83 primary public entry-point to their functionality.
77 84
  85 +**New in 0.2.2-SNAPSHOT:** The namespace **clojure.tools.namespace.move**
  86 +contains utilities to aid in moving and renaming Clojure namespaces.
  87 +This code is ALPHA and subject to change.
  88 +
78 89
79 90 Reloading Code: Motivation
80 91 ----------------------------
@@ -115,6 +126,7 @@ compile. I wrote tools.namespace to help speed up this development
115 126 cycle.
116 127
117 128
  129 +
118 130 Reloading Code: Usage
119 131 -----------------------
120 132
@@ -153,6 +165,7 @@ state stored in a Var that got deleted by `refresh`.
153 165 This brings us to the next section:
154 166
155 167
  168 +
156 169 Reloading Code: Preparing Your Application
157 170 --------------------------------------------
158 171
@@ -160,6 +173,7 @@ Being able to safely destroy and reload namespaces without breaking
160 173 your application requires some discipline and careful design. It won't
161 174 "just work" on any Clojure project.
162 175
  176 +
163 177 ### No Global State
164 178
165 179 The first rule for making your application reload-safe is **no global
@@ -186,19 +200,14 @@ Typically you'll still need one global `def` somewhere, perhaps in the
186 200 REPL itself, to hold the current application instance. See "Managing
187 201 Reloads" below.
188 202
  203 +
189 204 ### Managed Lifecycle
190 205
191 206 The second rule for making your application reload-safe is having a
192 207 consistent way to **start and stop the entire system**. I like to do
193 208 this with a protocol implemented by each major component in the
194   -system:
195   -
196   - (defprotocol Lifecycle
197   - (start [component])
198   - (stop [component]))
199   -
200   -Smaller applications can probably get along fine with just a pair of
201   -functions.
  209 +system, but smaller applications can probably get along fine with just
  210 +a pair of functions.
202 211
203 212 The point is that you need a convenient way to destroy all the
204 213 built-up state of your application and then *recreate it from
@@ -236,6 +245,7 @@ but see warnings below.)
236 245 After that, you've got a squeaky-clean new instance of your app
237 246 running, in a fraction of the time it takes to restart the JVM.
238 247
  248 +
239 249 ### Handling Errors
240 250
241 251 If an exception is thrown while loading a namespace, `refresh` stops,
@@ -272,6 +282,7 @@ If your current REPL namespace is one of those that has not yet been
272 282 reloaded, then you will need to call `refresh` by its fully-qualified
273 283 name `clojure.tools.namespace.repl/refresh`.
274 284
  285 +
275 286 ### Managing Reloads
276 287
277 288 Some projects have a "project REPL" or a "scratch" namespace where you
@@ -287,6 +298,7 @@ will break if the namespace *containing* the alias is not reloaded
287 298 also.
288 299
289 300
  301 +
290 302 Warnings
291 303 --------------------
292 304
@@ -327,6 +339,7 @@ This won't work if the namespace containing `restart` could get
327 339 reloaded. After `refresh`, the namespace containing `restart` has been
328 340 dropped, but the function continues to run in the *old* namespace.
329 341
  342 +
330 343 ### Warnings for Aliases
331 344
332 345 Namespace aliases created at the REPL will still refer to the *old* namespace after `refresh`. For example:
@@ -354,6 +367,7 @@ The only way out is to remove the alias before recreating it:
354 367 nil
355 368 user=> (alias 'foo 'com.example.foo)
356 369
  370 +
357 371 ### Warnings for Protocols
358 372
359 373 When reloading namespaces which contain protocols, be careful that you
@@ -393,23 +407,43 @@ To avoid this problem, always create new instances of records after a
393 407 refresh.
394 408
395 409
396   -Change Log
397   -========================================
398 410
  411 +Change Log
  412 +----------------------------------------
  413 +
  414 +* Version 0.2.2-SNAPSHOT (in development)
  415 + * Add `clojure.tools.namespace.move`
  416 + * Fix [TNS-4], reflection warnings
  417 +* Version 0.2.1 on 26-Oct-2012
  418 + * Restore deprecated 0.1.x APIs in `clojure.tools.namespace`
  419 + * Fix [TNS-3], actually use `refresh-dirs`
399 420 * Version 0.2.0 on 05-Oct-2012
400 421 * **Breaking API changes** from previous versions
401 422 * New dependency tracking & reloading features
  423 + * Eliminate dependency on [java.classpath]
402 424 * Version 0.1.3 on 24-Apr-2012
  425 + * Workaround for Clojure 1.2 reader bug
403 426 * Version 0.1.2 on 10-Feb-2012
  427 + * Eliminate reflection warnings
404 428 * Version 0.1.1 on 18-May-2011
405 429 * Version 0.1.0 on 24-Apr-2011
406 430 * Source-compatible with clojure.contrib.find-namespaces in old clojure-contrib 1.2.0
407 431
  432 +[TNS-3]: http://dev.clojure.org/jira/browse/TNS-3
  433 +[TNS-4]: http://dev.clojure.org/jira/browse/TNS-4
  434 +[java.classpath]: https://github.com/clojure/java.classpath
  435 +
408 436
409   -Copyright and License
410   -========================================
411 437
412   -Copyright © 2012 Stuart Sierra
  438 +Copyright and License
  439 +----------------------------------------
413 440
414   -Licensed under the [Eclipse Public License Version 1.0](https://github.com/clojure/tools.namespace/blob/master/epl.html).
  441 +Copyright © 2012 Stuart Sierra All rights reserved. The use and
  442 +distribution terms for this software are covered by the
  443 +[Eclipse Public License 1.0] which can be found in the file
  444 +epl-v10.html at the root of this distribution. By using this software
  445 +in any fashion, you are agreeing to be bound by the terms of this
  446 +license. You must not remove this notice, or any other, from this
  447 +software.
415 448
  449 +[Eclipse Public License 1.0]: http://opensource.org/licenses/eclipse-1.0.php
77 src/main/clojure/clojure/tools/namespace/move.clj
... ... @@ -0,0 +1,77 @@
  1 +;; Copyright (c) Stuart Sierra, 2012. All rights reserved. The use and
  2 +;; distribution terms for this software are covered by the Eclipse
  3 +;; Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
  4 +;; which can be found in the file epl-v10.html at the root of this
  5 +;; distribution. By using this software in any fashion, you are
  6 +;; agreeing to be bound by the terms of this license. You must not
  7 +;; remove this notice, or any other, from this software.
  8 +
  9 +(ns clojure.tools.namespace.move
  10 + (:require [clojure.string :as str]
  11 + [clojure.java.io :as io])
  12 + (:import (java.io File)))
  13 +
  14 +(defn- update-file
  15 + "Read file as a string, call f on file plus any args, then write out
  16 + return value of f as the new contents of file."
  17 + [file f & args]
  18 + (spit file (str (apply f (slurp file) args))))
  19 +
  20 +(defn- ns-file-name [sym]
  21 + (str (-> (name sym)
  22 + (str/replace #"-" "_")
  23 + (str/replace #"\." File/separator))
  24 + ".clj"))
  25 +
  26 +(defn- clojure-source-files [dirs]
  27 + (->> dirs
  28 + (map io/file)
  29 + (filter #(.exists %))
  30 + (mapcat file-seq)
  31 + (filter #(and (.isFile %) (.endsWith (.getName %) ".clj")))
  32 + (map #(.getCanonicalFile %))))
  33 +
  34 +(def ^:private symbol-regex
  35 + ;; LispReader.java uses #"[:]?([\D&&[^/]].*/)?([\D&&[^/]][^/]*)" but
  36 + ;; that's too broad; we don't want a whole namespace-qualified symbol,
  37 + ;; just each part individually.
  38 + #"[a-zA-Z0-9$%*+=?!<>_-]['.a-zA-Z0-9$%*+=?!<>_-]*")
  39 +
  40 +(defn replace-ns-symbol
  41 + "ALPHA: subject to change. Given Clojure source as a string, replaces
  42 + all occurances of the namespace name old-sym with new-sym and
  43 + returns modified source as a string."
  44 + [source old-sym new-sym]
  45 + (let [old-name (name old-sym)
  46 + new-name (name new-sym)]
  47 + ;; A lossless parser would be better, but this is adequate
  48 + (str/replace source symbol-regex
  49 + (fn [match]
  50 + (if (= match old-name)
  51 + new-name
  52 + match)))))
  53 +
  54 +(defn move-ns-file
  55 + "ALPHA: subject to change. Moves the .clj source file (found relative
  56 + to source-path) for the namespace named old-sym to a file for a
  57 + namespace named new-sym."
  58 + [old-sym new-sym source-path]
  59 + (let [old-file (io/file source-path (ns-file-name old-sym))
  60 + new-file (io/file source-path (ns-file-name new-sym))]
  61 + (.mkdirs (.getParentFile new-file))
  62 + (io/copy old-file new-file)
  63 + (.delete old-file)
  64 + (loop [dir (.getParentFile old-file)]
  65 + (when (empty? (.listFiles dir))
  66 + (.delete dir)
  67 + (recur (.getParentFile dir))))))
  68 +
  69 +(defn move-ns
  70 + "ALPHA: subject to change. Moves the .clj source file (found relative
  71 + to source-path) for the namespace named old-sym to new-sym
  72 + and replace all occurances of the old name with the new
  73 + name in all Clojure source files found in dirs."
  74 + [old-sym new-sym source-path dirs]
  75 + (move-ns-file old-sym new-sym source-path)
  76 + (doseq [file (clojure-source-files dirs)]
  77 + (update-file file replace-ns-symbol old-sym new-sym)))

No commit comments for this range

Something went wrong with that request. Please try again.