Last active
August 29, 2015 13:57
-
-
Save debetimi/9908652 to your computer and use it in GitHub Desktop.
Learning Clojure - Package Manager
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;;dddd | |
(ns package_manager | |
(:use [clojure.string :only [split, lower-case]])) | |
(def system (atom {})) | |
(def installed (atom (sorted-set))) | |
(def running (atom true)) | |
(defn in? [coll elm] | |
(some #{elm} coll)) | |
(defn package | |
"makes a package element with provided name, option list of providers | |
are packages requried by package, optional list of clients are packages using | |
package" | |
([name] | |
(package name #{} #{})) | |
([name providers clients] | |
{:name name, :providers providers, :clients clients})) | |
(defn add-client [pkg client] | |
(package (:name pkg) (:providers pkg) (conj (:clients pkg) client))) | |
(defn remove-client [pkg client] | |
(package (:name pkg) (:providers pkg) (disj (:clients pkg) client))) | |
(defn add-provider | |
([pkg] pkg) | |
([pkg provider] | |
(package (:name pkg) (conj (:providers pkg) provider) (:clients pkg))) | |
([pkg provider & more-providers] | |
(reduce add-provider pkg (cons provider more-providers)))) | |
(defn providers [pkg] | |
(get-in @system [pkg :providers ])) | |
(defn clients [pkg] | |
(get-in @system [pkg :clients ])) | |
(defn retrieve [pkg] | |
(get @system pkg)) | |
(defn exists? [pkg] | |
(contains? @system pkg)) | |
(defn dependent? [first second] | |
(if (in? (cons first (providers first)) second) | |
(do (println (str "\t" first) "depends on" second) true) | |
(some #(dependent? % second) (providers first)))) | |
(defn update! [pkg] | |
(swap! system assoc (:name pkg) pkg)) | |
(defn create! [pkg & deps] | |
(doseq [dep deps] | |
(if-not (exists? dep) (update! (package dep)))) | |
(if (not-any? #(dependent? % pkg) deps) | |
(update! (apply add-provider (cons (package pkg) deps))) | |
(println "Ignoring command"))) | |
(defn print-sys [] | |
(doseq [[k,v] @system] (println "\t" v))) | |
(defn print-installed [] | |
(doseq [v @installed] (println "\t" v))) | |
(defn installed? [pkg] | |
(contains? @installed pkg)) | |
(defn sys-install! [pkg] | |
(println "\t installing" pkg) | |
(swap! installed conj pkg)) | |
(defn install! [pkg & {:keys [is-dep]}] | |
(if-not (exists? pkg) (create! pkg)) | |
(if-not (installed? pkg) | |
(do | |
(doseq [provider (providers pkg)] | |
(if-not (installed? provider) (install! provider :is-dep true))) | |
(doseq [provider (providers pkg)] | |
(update! (add-client (retrieve provider) pkg))) | |
(if-not is-dep (update! (add-client (retrieve pkg) pkg))) | |
(sys-install! pkg)) | |
(do | |
(if-not is-dep (update! (add-client (retrieve pkg) pkg))) | |
(println "\t" pkg "is already installed.")))) | |
(defn needed? [pkg & {:keys [is-dep]}] | |
(let [pkg-clients (if is-dep | |
(clients pkg) | |
(disj (clients pkg) pkg))] | |
(not (empty? pkg-clients)))) | |
(defn sys-uninstall! [pkg] | |
(println "\t uninstalling" pkg) | |
(swap! installed disj pkg)) | |
(defn uninstall! [pkg & {:keys [is-dep]}] | |
(cond | |
(not (installed? pkg)) | |
(println "\t" pkg "is not installed.") | |
(needed? pkg :is-dep is-dep) | |
(println "\t" pkg "is still needed.") | |
:else (do | |
(doseq [provider (providers pkg)] | |
(update! (remove-client (retrieve provider) pkg))) | |
(update! (remove-client (retrieve pkg) pkg)) | |
(sys-uninstall! pkg) | |
(doseq [provider (filter #(not (needed? % :is-dep true)) | |
(providers pkg))] | |
(uninstall! provider :is-dep true))))) | |
(defn stop! [] | |
(reset! running false)) | |
(defn exit [] | |
(println "goodbye") (stop!)) | |
(defn run [] | |
(println "clojure package manager") | |
(reset! running true) | |
(while (true? @running) | |
(let [line (read-line) | |
[command & args] (split line #"\s+")] | |
(case (-> command lower-case keyword) | |
:depend (apply create! args) | |
:list (print-installed) | |
:install (doseq [pkg args] (install! pkg)) | |
:info (println (retrieve (first args))) | |
(:remove :uninstall ) (doseq [pkg args] (uninstall! pkg)) | |
:sys (print-sys) | |
(:exit :end ) (exit) | |
nil)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment