<commit_before>(ns 
  leiningen.ancient.utils.io
  (:require [clojure.java.io :as io :only [file writer]]
            [leiningen.core.project :as prj]
            [leiningen.core.main :as main]
            [ancient-clj.verbose :refer :all]
            [clojure.tools.reader.edn :as edn])
  (:import java.io.File))

;; ## Configure Logging

(defmacro with-output-settings
  "Configure Output/Verbose."
  [settings & body]
  `(with-settings ~settings
     (with-verbose main/debug
       ~@body)))

;; ## Console Interaction

(defn prompt
  "Create a yes/no prompt using the given message."
  [& msg]
  (let [msg (str (apply str msg) " [yes/no] ")]
    (loop [i 3]
      (when (pos? i)
        (print msg)
        (.flush ^java.io.Writer *out*)
        (let [r (or (read-line) "")
              r (.toLowerCase ^String r)]
          (cond (= r "yes") true
                (= r "no") false
                :else (recur (dec i))))))))

;; ## Backup/Data Files

(defn create-backup-file!
  "Create backup of a given File. Print errors and return `nil` if a failure occurs."
  ^File
  [^File f settings]
  (let [^File parent (.getParentFile f)
        ^File backup (io/file parent (str (.getName f) ".backup"))]
    (try
      (when (or (:overwrite-backup settings)
                (not (.exists backup))
                (prompt "Do you want to overwrite the existing backup file?")) 
        (verbose "Creating backup at: " (.getCanonicalPath backup))
        (io/copy f backup) 
        backup)
      (catch Exception ex
        (main/info (red "Could not create backup file:") (.getMessage ex))
        nil))))

(defn delete-backup-file!
  [^File backup]
  (try
    (verbose "Deleting backup file ...")
    (.delete backup)
    (catch Exception ex 
      (main/info (red "Could not delete backup file " (.getPath backup) ":") (.getMessage ex)))))

(defn replace-with-backup!
  [^File f ^File backup]
  (try
    (verbose "Replacing original file with backup file ...")
    (.delete f)
    (io/copy backup f)
    (.delete backup)
    (catch Exception ex
      (main/info (red "Could not replace original file " (.getPath f) ":") (.getMessage ex)))))

;; ## Project Map

(defn read-project-map!
  "Read project map from given file."
  [path]
  (try
    (locking read-project-map!
      (binding [*ns* (find-ns 'leiningen.core.project)]
        (load-file path)
        (when-let [project (resolve 'leiningen.core.project/project)]
          (ns-unmap 'leiningen.core.project 'project)
          @project)))
    (catch Exception ex
      (main/info "ERROR: Could not read project map from file:" path)
      (main/info "ERROR:" (.getMessage ex))))) 

;; ## Profiles File

(defn read-profiles-map!
  [path]
  (try
    (when-let [form  (edn/read-string (slurp path))]
      (when-not (map? form)
        (throw (Exception. (str "Not a map: " form))))
      form)
    (catch Exception ex
      (main/info "ERROR: Could not read profiles map from file:" path)
      (main/info "ERROR:" (.getMessage ex)))))<commit_msg>Using Clojure reader for profiles map instead of EDN reader. (fix #19)<commit_after>(ns 
  leiningen.ancient.utils.io
  (:require [clojure.java.io :as io :only [file writer]]
            [leiningen.core.project :as prj]
            [leiningen.core.main :as main]
            [ancient-clj.verbose :refer :all]
            [clojure.tools.reader :as reader])
  (:import java.io.File))

;; ## Configure Logging

(defmacro with-output-settings
  "Configure Output/Verbose."
  [settings & body]
  `(with-settings ~settings
     (with-verbose main/debug
       ~@body)))

;; ## Console Interaction

(defn prompt
  "Create a yes/no prompt using the given message."
  [& msg]
  (let [msg (str (apply str msg) " [yes/no] ")]
    (loop [i 3]
      (when (pos? i)
        (print msg)
        (.flush ^java.io.Writer *out*)
        (let [r (or (read-line) "")
              r (.toLowerCase ^String r)]
          (cond (= r "yes") true
                (= r "no") false
                :else (recur (dec i))))))))

;; ## Backup/Data Files

(defn create-backup-file!
  "Create backup of a given File. Print errors and return `nil` if a failure occurs."
  ^File
  [^File f settings]
  (let [^File parent (.getParentFile f)
        ^File backup (io/file parent (str (.getName f) ".backup"))]
    (try
      (when (or (:overwrite-backup settings)
                (not (.exists backup))
                (prompt "Do you want to overwrite the existing backup file?")) 
        (verbose "Creating backup at: " (.getCanonicalPath backup))
        (io/copy f backup) 
        backup)
      (catch Exception ex
        (main/info (red "Could not create backup file:") (.getMessage ex))
        nil))))

(defn delete-backup-file!
  [^File backup]
  (try
    (verbose "Deleting backup file ...")
    (.delete backup)
    (catch Exception ex 
      (main/info (red "Could not delete backup file " (.getPath backup) ":") (.getMessage ex)))))

(defn replace-with-backup!
  [^File f ^File backup]
  (try
    (verbose "Replacing original file with backup file ...")
    (.delete f)
    (io/copy backup f)
    (.delete backup)
    (catch Exception ex
      (main/info (red "Could not replace original file " (.getPath f) ":") (.getMessage ex)))))

;; ## Project Map

(defn read-project-map!
  "Read project map from given file."
  [path]
  (try
    (locking read-project-map!
      (binding [*ns* (find-ns 'leiningen.core.project)]
        (load-file path)
        (when-let [project (resolve 'leiningen.core.project/project)]
          (ns-unmap 'leiningen.core.project 'project)
          @project)))
    (catch Exception ex
      (main/info "ERROR: Could not read project map from file:" path)
      (main/info "ERROR:" (.getMessage ex))))) 

;; ## Profiles File

(defn read-profiles-map!
  [path]
  (try
    (when-let [form  (reader/read-string (slurp path))]
      (when-not (map? form)
        (throw (Exception. (str "Not a map: " form))))
      form)
    (catch Exception ex
      (main/info "ERROR: Could not read profiles map from file:" path)
      (main/info "ERROR:" (.getMessage ex)))))
{'fraction_non_alphanumeric': 0.1477029474724189, 'fraction_numerical': 0.0006586530545035403, 'mean_word_length': 2.427765237020316, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4132925', 'n_tokens_mistral': 1998, 'n_tokens_neox': 1920, 'n_words': 624}