From bba68b6e40c872b76450071aab5d22bb10c79e47 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Wed, 18 Sep 2013 10:40:29 +0200
Subject: [PATCH] only delete links; delete existing destination before
 creating links

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 cdist/conf/type/__link/explorer/type          | 26 ++++++++++++++++
 cdist/conf/type/__link/gencode-remote         | 30 ++++++++++++++++---
 .../conf/type/__link/parameter/default/state  |  1 +
 3 files changed, 53 insertions(+), 4 deletions(-)
 create mode 100755 cdist/conf/type/__link/explorer/type
 create mode 100644 cdist/conf/type/__link/parameter/default/state

diff --git a/cdist/conf/type/__link/explorer/type b/cdist/conf/type/__link/explorer/type
new file mode 100755
index 00000000..c02b3af8
--- /dev/null
+++ b/cdist/conf/type/__link/explorer/type
@@ -0,0 +1,26 @@
+#!/bin/sh
+# 2013 Steven Armstrong (steven-cdist armstrong.cc)
+
+destination="/$__object_id"
+
+if [ ! -e "$destination" ]; then
+   echo none
+elif [ -h "$destination" ]; then
+   echo symlink
+elif [ -f "$destination" ]; then
+   type="$(cat "$__object/parameter/type")"
+   case "$type" in
+      hard)
+         link_count=$(ls -l "$destination" | awk '{ print $2 }')
+         if [ $link_count -gt 1 ]; then
+            echo hardlink
+            exit 0
+         fi
+      ;;
+   esac
+   echo file
+elif [ -d "$destination" ]; then
+   echo directory
+else
+   echo unknown
+fi
diff --git a/cdist/conf/type/__link/gencode-remote b/cdist/conf/type/__link/gencode-remote
index 2975ef69..2e41b7d9 100755
--- a/cdist/conf/type/__link/gencode-remote
+++ b/cdist/conf/type/__link/gencode-remote
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
 # 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
+# 2013 Steven Armstrong (steven-cdist at armstrong.cc)
 #
 # This file is part of cdist.
 #
@@ -40,17 +41,38 @@ case "$type" in
 esac
 
 state_is="$(cat "$__object/explorer/state")"
-state_should=present
-[ -f "$__object/parameter/state" ] && state_should="$(cat "$__object/parameter/state")"
+state_should="$(cat "$__object/parameter/state")"
 
 [ "$state_should" = "$state_is" ] && exit 0
 
+file_type="$(cat "$__object/explorer/type")"
 case "$state_should" in
     present)
-        echo ln ${lnopt} -f \"$source\" \"$destination\"
+        if [ "$file_type" = "directory" ]; then
+            # our destination is currently a directory, move it out of the way
+            cat << DONE
+destination_old="\$(mktemp "${destination}.cdist.XXXXXXXXXX")"
+mv "$destination" "\$destination_old"
+DONE
+        fi
+
+        # create our link
+        cat << DONE
+ln ${lnopt} -f "$source" "$destination"
+DONE
+
+        if [ "$file_type" = "directory" ]; then
+            # delete the legacy directory
+            cat << DONE
+rm -rf "\$destination_old"
+DONE
+        fi
     ;;
     absent)
-        echo rm -f \"$destination\"
+        # only delete if it is a sym/hard link
+        if [ "$file_type" = "symlink" -o "$file_type" = "hardlink" ]; then
+            echo rm -f \"$destination\"
+        fi
     ;;
     *)
         echo "Unknown state: $state_should" >&2
diff --git a/cdist/conf/type/__link/parameter/default/state b/cdist/conf/type/__link/parameter/default/state
new file mode 100644
index 00000000..e7f6134f
--- /dev/null
+++ b/cdist/conf/type/__link/parameter/default/state
@@ -0,0 +1 @@
+present