From ac36b5e18db16595c22cb43dfe673de77f2adb98 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 13:31:22 +0100
Subject: [PATCH 01/98] template for new type that starts stuff on boot

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/cksum     | 34 ++++++++++
 conf/type/__start_on_boot/explorer/exists    | 30 +++++++++
 conf/type/__start_on_boot/gencode-local      | 43 ++++++++++++
 conf/type/__start_on_boot/gencode-remote     | 66 +++++++++++++++++++
 conf/type/__start_on_boot/man.text           | 69 ++++++++++++++++++++
 conf/type/__start_on_boot/manifest           | 24 +++++++
 conf/type/__start_on_boot/parameter/optional |  5 ++
 7 files changed, 271 insertions(+)
 create mode 100755 conf/type/__start_on_boot/explorer/cksum
 create mode 100755 conf/type/__start_on_boot/explorer/exists
 create mode 100755 conf/type/__start_on_boot/gencode-local
 create mode 100755 conf/type/__start_on_boot/gencode-remote
 create mode 100644 conf/type/__start_on_boot/man.text
 create mode 100755 conf/type/__start_on_boot/manifest
 create mode 100644 conf/type/__start_on_boot/parameter/optional

diff --git a/conf/type/__start_on_boot/explorer/cksum b/conf/type/__start_on_boot/explorer/cksum
new file mode 100755
index 00000000..dcad99ba
--- /dev/null
+++ b/conf/type/__start_on_boot/explorer/cksum
@@ -0,0 +1,34 @@
+#!/bin/sh
+#
+# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+# Retrieve the md5sum of a file to be created, if it is already existing.
+#
+
+destination="/$__object_id"
+
+if [ -e "$destination" ]; then
+   if [ -f  "$destination" ]; then
+      cksum < "$destination"
+   else
+      echo "NO REGULAR FILE"
+   fi
+else
+   echo "NO FILE FOUND, NO CHECKSUM CALCULATED."
+fi
diff --git a/conf/type/__start_on_boot/explorer/exists b/conf/type/__start_on_boot/explorer/exists
new file mode 100755
index 00000000..f8b85671
--- /dev/null
+++ b/conf/type/__start_on_boot/explorer/exists
@@ -0,0 +1,30 @@
+#!/bin/sh
+#
+# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+# Check whether file exists or not
+#
+
+destination="/$__object_id"
+
+if [ -e "$destination" ]; then
+   echo yes
+else
+   echo no
+fi
diff --git a/conf/type/__start_on_boot/gencode-local b/conf/type/__start_on_boot/gencode-local
new file mode 100755
index 00000000..d9839a19
--- /dev/null
+++ b/conf/type/__start_on_boot/gencode-local
@@ -0,0 +1,43 @@
+#!/bin/sh
+#
+# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+# __file is a very basic type, which will probably be reused quite often
+#
+
+destination="/$__object_id"
+state_should="$(cat "$__object/parameter/state")"
+
+if [ "$state_should" = "present" ]; then
+   if [ -f "$__object/parameter/source" ]; then
+      source="$(cat "$__object/parameter/source")"
+
+      if [ -f "$source" ]; then
+         local_cksum="$(cksum < "$source")"
+         remote_cksum="$(cat "$__object/explorer/cksum")"
+
+         if [ "$local_cksum" != "$remote_cksum" ]; then
+            echo "$__remote_copy" "$source" "${__target_host}:${destination}"
+         fi
+      else
+         echo "Source \"$source\" does not exist." >&2
+         exit 1
+      fi
+   fi
+fi
diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
new file mode 100755
index 00000000..9e700934
--- /dev/null
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -0,0 +1,66 @@
+#!/bin/sh
+#
+# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+# __file is a very basic type, which will probably be reused quite often
+#
+
+destination="/$__object_id"
+state_should="$(cat "$__object/parameter/state")"
+exists="$(cat "$__object/explorer/exists")"
+
+case "$state_should" in
+   present)
+      # No source? Create empty file
+      if [ ! -f "$__object/parameter/source" ]; then
+         if [ "$exists" = "no" ]; then
+            echo touch \"$destination\"
+         fi
+      fi
+
+      # Mode settings
+      if [ -f "$__object/parameter/mode" ]; then
+         echo chmod \"$(cat "$__object/parameter/mode")\" \"$destination\"
+      fi
+
+      # Group
+      if [ -f "$__object/parameter/group" ]; then
+         echo chgrp \"$(cat "$__object/parameter/group")\" \"$destination\"
+      fi
+
+      # Owner
+      if [ -f "$__object/parameter/owner" ]; then
+         echo chown \"$(cat "$__object/parameter/owner")\" \"$destination\"
+      fi
+   ;;
+
+   absent)
+
+      if [ "$exists" = "yes" ]; then
+         echo rm -f \"$destination\"
+      fi
+
+   ;;
+
+   *)
+      echo "Unknown state: $state_should" >&2
+      exit 1
+   ;;
+
+esac
diff --git a/conf/type/__start_on_boot/man.text b/conf/type/__start_on_boot/man.text
new file mode 100644
index 00000000..5e91599f
--- /dev/null
+++ b/conf/type/__start_on_boot/man.text
@@ -0,0 +1,69 @@
+cdist-type__file(7)
+===================
+Nico Schottelius <nico-cdist--@--schottelius.org>
+
+
+NAME
+----
+cdist-type__file - Manage files
+
+
+DESCRIPTION
+-----------
+This cdist type allows you to create files, remove files and set file
+attributes on the target.
+
+
+REQUIRED PARAMETERS
+-------------------
+None.
+
+OPTIONAL PARAMETERS
+-------------------
+state::
+   'present' or 'absent', defaults to 'present'
+
+group::
+   Group to chgrp to.
+
+mode::
+   Unix permissions, suitable for chmod.
+
+owner::
+   User to chown to.
+
+source::
+   If supplied, copy this file from the host running cdist to the target.
+   If not supplied, an empty file or directory will be created.
+
+
+EXAMPLES
+--------
+
+--------------------------------------------------------------------------------
+# Create  /etc/cdist-configured as an empty file
+__file /etc/cdist-configured
+# The same thing
+__file /etc/cdist-configured --state present
+# Delete existing file
+__file /etc/cdist-configured --state absent
+
+# Use __file from another type
+__file /etc/issue --source "$__type/files/archlinux" --state present
+
+# Supply some more settings
+__file /etc/shadow --source "$__type/files/shadow" \
+   --owner root --group shadow --mode 0640 \
+   --state present
+--------------------------------------------------------------------------------
+
+
+SEE ALSO
+--------
+- cdist-type(7)
+
+
+COPYING
+-------
+Copyright \(C) 2011-2012 Nico Schottelius. Free use of this software is
+granted under the terms of the GNU General Public License version 3 (GPLv3).
diff --git a/conf/type/__start_on_boot/manifest b/conf/type/__start_on_boot/manifest
new file mode 100755
index 00000000..6b5e1ca7
--- /dev/null
+++ b/conf/type/__start_on_boot/manifest
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# 2011 Steven Armstrong (steven-cdist at armstrong.cc)
+# 2012 Nico Schottelius (nico-cdist at schottelius.org)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# set default: present, if not setup
+statefile="$__object/parameter/state"
+[ -f "$statefile" ] || echo present > "$statefile"
diff --git a/conf/type/__start_on_boot/parameter/optional b/conf/type/__start_on_boot/parameter/optional
new file mode 100644
index 00000000..c696d592
--- /dev/null
+++ b/conf/type/__start_on_boot/parameter/optional
@@ -0,0 +1,5 @@
+state
+group
+mode
+owner
+source

From c567ade17a2072d502613a059e99ce7e812faf6e Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 14:42:36 +0100
Subject: [PATCH 02/98] add manpage for __start_on_boot

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/man.text | 43 +++++++++---------------------
 1 file changed, 12 insertions(+), 31 deletions(-)

diff --git a/conf/type/__start_on_boot/man.text b/conf/type/__start_on_boot/man.text
index 5e91599f..e9691401 100644
--- a/conf/type/__start_on_boot/man.text
+++ b/conf/type/__start_on_boot/man.text
@@ -1,17 +1,17 @@
-cdist-type__file(7)
-===================
+cdist-type__start_on_boot(7)
+============================
 Nico Schottelius <nico-cdist--@--schottelius.org>
 
 
 NAME
 ----
-cdist-type__file - Manage files
+cdist-type__start_on_boot - Manage stuff to be started at boot
 
 
 DESCRIPTION
 -----------
-This cdist type allows you to create files, remove files and set file
-attributes on the target.
+This cdist type allows you to enable or disable stuff to be started
+at boot of your operating system.
 
 
 REQUIRED PARAMETERS
@@ -23,38 +23,19 @@ OPTIONAL PARAMETERS
 state::
    'present' or 'absent', defaults to 'present'
 
-group::
-   Group to chgrp to.
-
-mode::
-   Unix permissions, suitable for chmod.
-
-owner::
-   User to chown to.
-
-source::
-   If supplied, copy this file from the host running cdist to the target.
-   If not supplied, an empty file or directory will be created.
-
 
 EXAMPLES
 --------
 
 --------------------------------------------------------------------------------
-# Create  /etc/cdist-configured as an empty file
-__file /etc/cdist-configured
-# The same thing
-__file /etc/cdist-configured --state present
-# Delete existing file
-__file /etc/cdist-configured --state absent
+# Ensure snmpd is started at boot
+__start_on_boot snmpd
 
-# Use __file from another type
-__file /etc/issue --source "$__type/files/archlinux" --state present
+# Same, but more explicit
+__start_on_boot snmpd --state present
 
-# Supply some more settings
-__file /etc/shadow --source "$__type/files/shadow" \
-   --owner root --group shadow --mode 0640 \
-   --state present
+# Ensure legacy configuration management will not be started
+__start_on_boot puppet --state absent
 --------------------------------------------------------------------------------
 
 
@@ -65,5 +46,5 @@ SEE ALSO
 
 COPYING
 -------
-Copyright \(C) 2011-2012 Nico Schottelius. Free use of this software is
+Copyright \(C) 2012 Nico Schottelius. Free use of this software is
 granted under the terms of the GNU General Public License version 3 (GPLv3).

From aea107079899f2c76ca0f0aa7a9a62f278f4a9e7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 14:50:50 +0100
Subject: [PATCH 03/98] add global explorer runlevel

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/explorer/runlevel | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)
 create mode 100755 conf/explorer/runlevel

diff --git a/conf/explorer/runlevel b/conf/explorer/runlevel
new file mode 100755
index 00000000..7cdd81ef
--- /dev/null
+++ b/conf/explorer/runlevel
@@ -0,0 +1,26 @@
+#!/bin/sh
+#
+# 2012 Nico Schottelius (nico-cdist at schottelius.org)
+#
+# This file is part of cdist.
+#
+# cdist is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# cdist is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with cdist. If not, see <http://www.gnu.org/licenses/>.
+#
+#
+
+set +e
+executable=$(which runlevel 2>/dev/null)
+if [ -x "$executable" ]; then
+   "$executable" | awk '{ print $2 }'
+fi

From 14127446191d92ed343145a50dc04c9e66507c20 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 15:52:19 +0100
Subject: [PATCH 04/98] begin state explorer

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/exists     | 30 ----------------
 .../__start_on_boot/explorer/{cksum => state} | 34 ++++++++++++-------
 2 files changed, 22 insertions(+), 42 deletions(-)
 delete mode 100755 conf/type/__start_on_boot/explorer/exists
 rename conf/type/__start_on_boot/explorer/{cksum => state} (59%)

diff --git a/conf/type/__start_on_boot/explorer/exists b/conf/type/__start_on_boot/explorer/exists
deleted file mode 100755
index f8b85671..00000000
--- a/conf/type/__start_on_boot/explorer/exists
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/sh
-#
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
-#
-# This file is part of cdist.
-#
-# cdist is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# cdist is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with cdist. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# Check whether file exists or not
-#
-
-destination="/$__object_id"
-
-if [ -e "$destination" ]; then
-   echo yes
-else
-   echo no
-fi
diff --git a/conf/type/__start_on_boot/explorer/cksum b/conf/type/__start_on_boot/explorer/state
similarity index 59%
rename from conf/type/__start_on_boot/explorer/cksum
rename to conf/type/__start_on_boot/explorer/state
index dcad99ba..c68ec2ba 100755
--- a/conf/type/__start_on_boot/explorer/cksum
+++ b/conf/type/__start_on_boot/explorer/state
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+# 2012 Nico Schottelius (nico-cdist at schottelius.org)
 #
 # This file is part of cdist.
 #
@@ -18,17 +18,27 @@
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
 #
-# Retrieve the md5sum of a file to be created, if it is already existing.
+# Check whether the given name will be started on boot or not
 #
 
-destination="/$__object_id"
+os=$(cat "$__global/explorer/os")
+
+case "$os" in
+    debian|ubuntu)
+        echo update-rc.d \"$name\" defaults
+    ;;  
+
+    gentoo)
+        echo rc-update add \"$name\" default
+    ;;  
+
+    centos|fedora|owl|redhat)
+        echo chkconfig \"$name\" on
+    ;;  
+
+    *)  
+       echo "Unsupported os: $os" >&2
+       exit 1
+    ;;  
+esac
 
-if [ -e "$destination" ]; then
-   if [ -f  "$destination" ]; then
-      cksum < "$destination"
-   else
-      echo "NO REGULAR FILE"
-   fi
-else
-   echo "NO FILE FOUND, NO CHECKSUM CALCULATED."
-fi

From 6b6ae1bde225765051f7be1972c2fd463f789b48 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 15:52:47 +0100
Subject: [PATCH 05/98] document more exported environment variables

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/man/cdist-reference.text.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/man/cdist-reference.text.sh b/doc/man/cdist-reference.text.sh
index 6b4e786f..ffc40ee3 100755
--- a/doc/man/cdist-reference.text.sh
+++ b/doc/man/cdist-reference.text.sh
@@ -167,7 +167,7 @@ ENVIRONMENT VARIABLES
 ---------------------
 __explorer::
    Directory that contains all global explorers.
-   Available for: explorer
+   Available for: explorer, type explorer
 __manifest::
    Directory that contains the initial manifest.
    Available for: initial manifest
@@ -188,7 +188,7 @@ __object_name::
    Available for: type manifest, type explorer, type gencode
 __target_host::
    The host we are deploying to.
-   Available for: initial manifest, type manifest, type gencode
+   Available for: explorer, initial manifest, type explorer, type manifest, type gencode
 __type::
    Path to the current type.
    Available for: type manifest, type gencode

From 42e3c18d02823a47423ac194ef884a57fd741aa2 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 15:54:32 +0100
Subject: [PATCH 06/98] +update of __start_on_boot

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/state |  2 +-
 conf/type/__start_on_boot/gencode-remote | 71 ++++++++++++------------
 conf/type/__start_on_boot/man.text       |  3 +
 3 files changed, 39 insertions(+), 37 deletions(-)

diff --git a/conf/type/__start_on_boot/explorer/state b/conf/type/__start_on_boot/explorer/state
index c68ec2ba..136c1e05 100755
--- a/conf/type/__start_on_boot/explorer/state
+++ b/conf/type/__start_on_boot/explorer/state
@@ -21,7 +21,7 @@
 # Check whether the given name will be started on boot or not
 #
 
-os=$(cat "$__global/explorer/os")
+os=$("$__explorer/os")
 
 case "$os" in
     debian|ubuntu)
diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index 9e700934..5133810d 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+# 2012 Nico Schottelius (nico-cdist at schottelius.org)
 #
 # This file is part of cdist.
 #
@@ -18,49 +18,48 @@
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
 #
-# __file is a very basic type, which will probably be reused quite often
-#
 
-destination="/$__object_id"
-state_should="$(cat "$__object/parameter/state")"
-exists="$(cat "$__object/explorer/exists")"
+if [ -f "$__object/parameter/state" ]; then
+    state_should="$(cat "$__object/parameter/state")"
+else
+    state_should="present"
+fi
+
+os=$(cat "$__global/explorer/os")
+name="$__object_id"
+
+# Support runlevels later
+#runlevel=$(cat $__global/explorer/runlevel)
 
 case "$state_should" in
-   present)
-      # No source? Create empty file
-      if [ ! -f "$__object/parameter/source" ]; then
-         if [ "$exists" = "no" ]; then
-            echo touch \"$destination\"
-         fi
-      fi
+    present)
+        case "$os" in
+            debian|ubuntu)
+                echo update-rc.d \"$name\" defaults
+            ;;
 
-      # Mode settings
-      if [ -f "$__object/parameter/mode" ]; then
-         echo chmod \"$(cat "$__object/parameter/mode")\" \"$destination\"
-      fi
+            gentoo)
+                echo rc-update add \"$name\" default
+            ;;
 
-      # Group
-      if [ -f "$__object/parameter/group" ]; then
-         echo chgrp \"$(cat "$__object/parameter/group")\" \"$destination\"
-      fi
+            centos|fedora|owl|redhat)
+                echo echo chkconfig \"$name\" on
+            ;;
 
-      # Owner
-      if [ -f "$__object/parameter/owner" ]; then
-         echo chown \"$(cat "$__object/parameter/owner")\" \"$destination\"
-      fi
-   ;;
+            *)
+               echo "Unsupported os: $os" >&2
+               exit 1
+            ;;
+        esac
+    ;;
 
-   absent)
+    absent)
 
-      if [ "$exists" = "yes" ]; then
-         echo rm -f \"$destination\"
-      fi
+    ;;
 
-   ;;
-
-   *)
-      echo "Unknown state: $state_should" >&2
-      exit 1
-   ;;
 
+    *)
+        echo "Unknown state: $state_should" >&2
+        exit 1
+    ;;
 esac
diff --git a/conf/type/__start_on_boot/man.text b/conf/type/__start_on_boot/man.text
index e9691401..eb9dbe7f 100644
--- a/conf/type/__start_on_boot/man.text
+++ b/conf/type/__start_on_boot/man.text
@@ -23,6 +23,9 @@ OPTIONAL PARAMETERS
 state::
    'present' or 'absent', defaults to 'present'
 
+runlevel::
+   Specify runlevel(s) to affect. Defaults to default or current runlevel.
+
 
 EXAMPLES
 --------

From 1e9940ae53b3b517b4e90896ee8fac2a722e3162 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 15:54:50 +0100
Subject: [PATCH 07/98] ++fixme of logging

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/explorer.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/cdist/core/explorer.py b/lib/cdist/core/explorer.py
index 01c4c81d..19833d92 100644
--- a/lib/cdist/core/explorer.py
+++ b/lib/cdist/core/explorer.py
@@ -73,6 +73,7 @@ class Explorer(object):
             '__target_host': self.target_host,
             '__explorer': self.remote.global_explorer_path,
         }
+        # FIXME: remove soon with new logging infrastructure
         if self.log.getEffectiveLevel() == logging.DEBUG:
             self.env.update({'__debug': "yes" })
         self._type_explorers_transferred = []

From 5a383fcbad5c99e0c16dd365c0b94ca85cf9585f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 15:54:58 +0100
Subject: [PATCH 08/98] ++todo for nico

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/TAKEME   | 3 ---
 doc/dev/todo/niconext | 6 +++++-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/doc/dev/todo/TAKEME b/doc/dev/todo/TAKEME
index 875d2970..56bb8284 100644
--- a/doc/dev/todo/TAKEME
+++ b/doc/dev/todo/TAKEME
@@ -37,6 +37,3 @@ TYPES
 ------
 - __user
    add option to include --create-home
-- __init_script?
-    to enable/disable startup of init stuff
-    http://linuxhelp.blogspot.com/2006/04/enabling-and-disabling-services-during_01.html
diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index ad859266..4543b32a 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -1,4 +1,9 @@
+- __init_script?
+    to enable/disable startup of init stuff
+    http://linuxhelp.blogspot.com/2006/04/enabling-and-disabling-services-during_01.html
+
 - update/create docs
+    - document __remote_copy and __remote_exec
     - cdist-cache::
         How to get use information about the hosts we have been working on [advanced]
     - cdist-scaling-tuning::
@@ -12,4 +17,3 @@
 
     - exec flag is not true for manifest anymore
     - SSH HINTS - ssh agent
-

From 0ccf000713dc196686a80256fd543a15b499ce56 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 15:55:06 +0100
Subject: [PATCH 09/98] more stuff for 2.0.6

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/changelog | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/doc/changelog b/doc/changelog
index 062db392..5867d54d 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -7,6 +7,8 @@
 	* New Type: __rvm_gem (Evax Software)
 	* New Type: __rvm_gemset (Evax Software)
 	* New Type: __rvm_ruby (Evax Software)
+	* New Explorer: runlevel
+	* Documentation: Update of reference (environment variables)
 
 2.0.5: 2012-01-18
 	* Bugfix __key_value: Use correct delimiters

From fe0fae69023eca7561c6c01831b97f6e50a8e2c4 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 16:07:33 +0100
Subject: [PATCH 10/98] update explorer and gencode and parameter

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/state     |  5 ++-
 conf/type/__start_on_boot/gencode-local      | 43 --------------------
 conf/type/__start_on_boot/gencode-remote     | 25 +++++++++++-
 conf/type/__start_on_boot/man.text           |  1 +
 conf/type/__start_on_boot/parameter/optional |  4 --
 5 files changed, 29 insertions(+), 49 deletions(-)
 delete mode 100755 conf/type/__start_on_boot/gencode-local

diff --git a/conf/type/__start_on_boot/explorer/state b/conf/type/__start_on_boot/explorer/state
index 136c1e05..8db4b9d2 100755
--- a/conf/type/__start_on_boot/explorer/state
+++ b/conf/type/__start_on_boot/explorer/state
@@ -22,6 +22,7 @@
 #
 
 os=$("$__explorer/os")
+runlevel=$("$__explorer/runlevel")
 
 case "$os" in
     debian|ubuntu)
@@ -33,7 +34,8 @@ case "$os" in
     ;;  
 
     centos|fedora|owl|redhat)
-        echo chkconfig \"$name\" on
+        state=$(chkconfig --level "$runlevel" \"$name\" || echo absent)
+        [ "$state" ] || state="present"
     ;;  
 
     *)  
@@ -42,3 +44,4 @@ case "$os" in
     ;;  
 esac
 
+echo $state
diff --git a/conf/type/__start_on_boot/gencode-local b/conf/type/__start_on_boot/gencode-local
deleted file mode 100755
index d9839a19..00000000
--- a/conf/type/__start_on_boot/gencode-local
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/bin/sh
-#
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
-#
-# This file is part of cdist.
-#
-# cdist is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# cdist is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with cdist. If not, see <http://www.gnu.org/licenses/>.
-#
-#
-# __file is a very basic type, which will probably be reused quite often
-#
-
-destination="/$__object_id"
-state_should="$(cat "$__object/parameter/state")"
-
-if [ "$state_should" = "present" ]; then
-   if [ -f "$__object/parameter/source" ]; then
-      source="$(cat "$__object/parameter/source")"
-
-      if [ -f "$source" ]; then
-         local_cksum="$(cksum < "$source")"
-         remote_cksum="$(cat "$__object/explorer/cksum")"
-
-         if [ "$local_cksum" != "$remote_cksum" ]; then
-            echo "$__remote_copy" "$source" "${__target_host}:${destination}"
-         fi
-      else
-         echo "Source \"$source\" does not exist." >&2
-         exit 1
-      fi
-   fi
-fi
diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index 5133810d..aa854658 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -25,6 +25,11 @@ else
     state_should="present"
 fi
 
+state_is=$(cat "$__object/explorer/state")
+
+# Nothing todo, go away
+[ "$state_should" = "$state_is" ] && exit 0
+
 os=$(cat "$__global/explorer/os")
 name="$__object_id"
 
@@ -43,7 +48,7 @@ case "$state_should" in
             ;;
 
             centos|fedora|owl|redhat)
-                echo echo chkconfig \"$name\" on
+                echo chkconfig \"$name\" on
             ;;
 
             *)
@@ -54,7 +59,25 @@ case "$state_should" in
     ;;
 
     absent)
+        case "$os" in
+            debian|ubuntu)
+                echo update-rc.d -f \"$name\" remove
+            ;;
 
+            gentoo)
+                echo rc-update del \"$name\"
+            ;;
+
+            centos|fedora|owl|redhat)
+                echo chkconfig \"$name\" off
+            ;;
+
+            *)
+               echo "Unsupported os: $os" >&2
+               exit 1
+            ;;
+        esac
+ 
     ;;
 
 
diff --git a/conf/type/__start_on_boot/man.text b/conf/type/__start_on_boot/man.text
index eb9dbe7f..5614f16b 100644
--- a/conf/type/__start_on_boot/man.text
+++ b/conf/type/__start_on_boot/man.text
@@ -25,6 +25,7 @@ state::
 
 runlevel::
    Specify runlevel(s) to affect. Defaults to default or current runlevel.
+   NOT YET SUPPORTED, ALWAYS USING CURRENT RUNLEVEL.
 
 
 EXAMPLES
diff --git a/conf/type/__start_on_boot/parameter/optional b/conf/type/__start_on_boot/parameter/optional
index c696d592..ff72b5c7 100644
--- a/conf/type/__start_on_boot/parameter/optional
+++ b/conf/type/__start_on_boot/parameter/optional
@@ -1,5 +1 @@
 state
-group
-mode
-owner
-source

From 559670ab4f333b44831c29e18b70ab442275b8d9 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 16:15:53 +0100
Subject: [PATCH 11/98] add debian / ubuntu support for checking state

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/state | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/conf/type/__start_on_boot/explorer/state b/conf/type/__start_on_boot/explorer/state
index 8db4b9d2..2778e784 100755
--- a/conf/type/__start_on_boot/explorer/state
+++ b/conf/type/__start_on_boot/explorer/state
@@ -21,12 +21,19 @@
 # Check whether the given name will be started on boot or not
 #
 
+set -x 
+exec >&2
+
 os=$("$__explorer/os")
 runlevel=$("$__explorer/runlevel")
+name="$__object_id"
+
+# default
+state="present"
 
 case "$os" in
     debian|ubuntu)
-        echo update-rc.d \"$name\" defaults
+        [ -f "/etc/rc$runlevel.d/S"??"$name" ] || state="absent"
     ;;  
 
     gentoo)
@@ -45,3 +52,4 @@ case "$os" in
 esac
 
 echo $state
+exit 1

From aa870e012441a0a570aae87c35d45a11552609fb Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 18 Jan 2012 16:37:09 +0100
Subject: [PATCH 12/98] remove debug, remove gentoo support until tested

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/state |  8 --------
 conf/type/__start_on_boot/gencode-remote | 15 ++++++++-------
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/conf/type/__start_on_boot/explorer/state b/conf/type/__start_on_boot/explorer/state
index 2778e784..9d63b84e 100755
--- a/conf/type/__start_on_boot/explorer/state
+++ b/conf/type/__start_on_boot/explorer/state
@@ -21,9 +21,6 @@
 # Check whether the given name will be started on boot or not
 #
 
-set -x 
-exec >&2
-
 os=$("$__explorer/os")
 runlevel=$("$__explorer/runlevel")
 name="$__object_id"
@@ -36,10 +33,6 @@ case "$os" in
         [ -f "/etc/rc$runlevel.d/S"??"$name" ] || state="absent"
     ;;  
 
-    gentoo)
-        echo rc-update add \"$name\" default
-    ;;  
-
     centos|fedora|owl|redhat)
         state=$(chkconfig --level "$runlevel" \"$name\" || echo absent)
         [ "$state" ] || state="present"
@@ -52,4 +45,3 @@ case "$os" in
 esac
 
 echo $state
-exit 1
diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index aa854658..ee2bdeb6 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -43,9 +43,10 @@ case "$state_should" in
                 echo update-rc.d \"$name\" defaults
             ;;
 
-            gentoo)
-                echo rc-update add \"$name\" default
-            ;;
+# Disabled until the explorer is checked
+#            gentoo)
+#                echo rc-update add \"$name\" default
+#            ;;
 
             centos|fedora|owl|redhat)
                 echo chkconfig \"$name\" on
@@ -64,9 +65,10 @@ case "$state_should" in
                 echo update-rc.d -f \"$name\" remove
             ;;
 
-            gentoo)
-                echo rc-update del \"$name\"
-            ;;
+# Disabled until the explorer is checked
+#            gentoo)
+#                echo rc-update del \"$name\"
+#            ;;
 
             centos|fedora|owl|redhat)
                 echo chkconfig \"$name\" off
@@ -80,7 +82,6 @@ case "$state_should" in
  
     ;;
 
-
     *)
         echo "Unknown state: $state_should" >&2
         exit 1

From a112b4f123d591096bede64ba96545e911204edd Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Thu, 19 Jan 2012 09:12:54 +0100
Subject: [PATCH 13/98] documet debian/ubuntu problem

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index ee2bdeb6..5e9c6343 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -40,6 +40,9 @@ case "$state_should" in
     present)
         case "$os" in
             debian|ubuntu)
+                # This does not work as expected:
+                # insserv: warning: current start runlevel(s) (3 4 5) of script `postfix' overwrites defaults (2 3 4 5).
+                #echo update-rc.d \"$name\" defaults
                 echo update-rc.d \"$name\" defaults
             ;;
 

From aae67652e9cdb79c019c7c405e2a97e0d8c32f90 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 20 Jan 2012 12:57:40 +0100
Subject: [PATCH 14/98] explore state of init script on archlinux

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/state | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/conf/type/__start_on_boot/explorer/state b/conf/type/__start_on_boot/explorer/state
index 9d63b84e..1de1fe57 100755
--- a/conf/type/__start_on_boot/explorer/state
+++ b/conf/type/__start_on_boot/explorer/state
@@ -29,6 +29,23 @@ name="$__object_id"
 state="present"
 
 case "$os" in
+    archlinux)
+        # convert bash array to shell
+        daemons=$(grep ^DAEMONS /etc/rc.conf | sed -e 's/^.*=(//' -e 's/)$//')
+
+        # absent, as long as not found
+        state="absent"
+
+        # iterate, last one wins.
+        for daemon in $daemons; do
+            if [ "$daemon" = "$name" -o "$daemon" = "@${name}" ]; then
+                state="present"
+            elif [ "$daemon" = "!${name}" ]; then
+                state="absent"
+            fi
+        done
+    ;;  
+
     debian|ubuntu)
         [ -f "/etc/rc$runlevel.d/S"??"$name" ] || state="absent"
     ;;  

From bd32bd0953d3075b21586df15abee23f22eb99c7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 20 Jan 2012 12:58:50 +0100
Subject: [PATCH 15/98] setup state in os specific sections to get better
 overview

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/explorer/state | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/conf/type/__start_on_boot/explorer/state b/conf/type/__start_on_boot/explorer/state
index 1de1fe57..ff092a65 100755
--- a/conf/type/__start_on_boot/explorer/state
+++ b/conf/type/__start_on_boot/explorer/state
@@ -25,8 +25,6 @@ os=$("$__explorer/os")
 runlevel=$("$__explorer/runlevel")
 name="$__object_id"
 
-# default
-state="present"
 
 case "$os" in
     archlinux)
@@ -44,21 +42,23 @@ case "$os" in
                 state="absent"
             fi
         done
-    ;;  
+    ;;
 
     debian|ubuntu)
+        state="present"
         [ -f "/etc/rc$runlevel.d/S"??"$name" ] || state="absent"
-    ;;  
+    ;;
 
     centos|fedora|owl|redhat)
+        state="present"
         state=$(chkconfig --level "$runlevel" \"$name\" || echo absent)
         [ "$state" ] || state="present"
-    ;;  
+    ;;
 
     *)  
        echo "Unsupported os: $os" >&2
        exit 1
-    ;;  
+    ;;
 esac
 
 echo $state

From 4ea85fb40224da50eeb945fa0d1a366e846a0196 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 20 Jan 2012 13:12:14 +0100
Subject: [PATCH 16/98] ++todo (absent/present)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/TAKEME | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/doc/dev/todo/TAKEME b/doc/dev/todo/TAKEME
index 948aa1a5..abcd5097 100644
--- a/doc/dev/todo/TAKEME
+++ b/doc/dev/todo/TAKEME
@@ -36,3 +36,5 @@ TYPES
 ------
 - __user
    add option to include --create-home
+- ensure that all types, which support --state support
+    present and absent (consistent look and feel)

From 6d5c69d5c423b2dcb049b11618b4f15216213161 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 20 Jan 2012 14:16:49 +0100
Subject: [PATCH 17/98] remove runlevel parameter for now - seems to be too
 complex/unecessary for the moment

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/man.text | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/conf/type/__start_on_boot/man.text b/conf/type/__start_on_boot/man.text
index 5614f16b..e9691401 100644
--- a/conf/type/__start_on_boot/man.text
+++ b/conf/type/__start_on_boot/man.text
@@ -23,10 +23,6 @@ OPTIONAL PARAMETERS
 state::
    'present' or 'absent', defaults to 'present'
 
-runlevel::
-   Specify runlevel(s) to affect. Defaults to default or current runlevel.
-   NOT YET SUPPORTED, ALWAYS USING CURRENT RUNLEVEL.
-
 
 EXAMPLES
 --------

From a357d7d794990d3123a36c6690ccf5ac8ed979fb Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 20 Jan 2012 14:57:25 +0100
Subject: [PATCH 18/98] support adding start on boot on archlinux (no removal
 so far)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index 5e9c6343..c13013ad 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -33,12 +33,12 @@ state_is=$(cat "$__object/explorer/state")
 os=$(cat "$__global/explorer/os")
 name="$__object_id"
 
-# Support runlevels later
-#runlevel=$(cat $__global/explorer/runlevel)
-
 case "$state_should" in
     present)
         case "$os" in
+            archlinux)
+                echo sed -i /etc/rc.conf \"s/^\\(DAEMONS=.*\\))/\\1 foo)/\"
+            ;;
             debian|ubuntu)
                 # This does not work as expected:
                 # insserv: warning: current start runlevel(s) (3 4 5) of script `postfix' overwrites defaults (2 3 4 5).

From 6d14e32911c78130860718515115fe8a1ec248b1 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 20 Jan 2012 15:34:18 +0100
Subject: [PATCH 19/98] support removal and correct adding daemons on archlinux

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index c13013ad..61a6b465 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -37,7 +37,7 @@ case "$state_should" in
     present)
         case "$os" in
             archlinux)
-                echo sed -i /etc/rc.conf \"s/^\\(DAEMONS=.*\\))/\\1 foo)/\"
+                echo sed -i /etc/rc.conf \"s/^\\(DAEMONS=.*\\))/\\1 $name)/\"
             ;;
             debian|ubuntu)
                 # This does not work as expected:
@@ -64,6 +64,9 @@ case "$state_should" in
 
     absent)
         case "$os" in
+            archlinux)
+                echo sed -i /etc/rc.conf -e \"s/ $name / /g\" -e \"s/($name/(/\" -e \"s/ $name)/)/\"
+            ;;
             debian|ubuntu)
                 echo update-rc.d -f \"$name\" remove
             ;;

From 1b263b57cfde719eb8a8134555317201d1e8e0aa Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 20 Jan 2012 16:30:44 +0100
Subject: [PATCH 20/98] prefer ' over "

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index 61a6b465..09c4912d 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -37,7 +37,7 @@ case "$state_should" in
     present)
         case "$os" in
             archlinux)
-                echo sed -i /etc/rc.conf \"s/^\\(DAEMONS=.*\\))/\\1 $name)/\"
+                echo sed -i /etc/rc.conf \'s/^\\(DAEMONS=.*\\))/\\1 $name)/\'
             ;;
             debian|ubuntu)
                 # This does not work as expected:

From 85f7880c7ed4b86453e837bc781861ac0cd694e5 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Fri, 3 Feb 2012 20:50:17 +0100
Subject: [PATCH 21/98] add a hopefully more robust implementation for changing
 existing values

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 conf/type/__key_value/gencode-remote | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/conf/type/__key_value/gencode-remote b/conf/type/__key_value/gencode-remote
index eff0925c..08b3a0f3 100755
--- a/conf/type/__key_value/gencode-remote
+++ b/conf/type/__key_value/gencode-remote
@@ -40,10 +40,7 @@ DONE
          else
             # change value
             cat << DONE
-awk -F "$delimiter" '
-/${key}${delimiter}*/{gsub("$value_is", "$value_should")};{print}' "$file" > "${file}+" \
-&& mv "${file}+" "$file"
-
+sed -i "s|^$key\($delimiter\+\).*|$key\1$value_should|" "$file"
 DONE
          fi
       ;;

From 4628dad04576103945553609c9e46c71cee35de8 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Fri, 3 Feb 2012 20:55:24 +0100
Subject: [PATCH 22/98] cleaner way to set default values

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 conf/type/__key_value/explorer/value | 8 +++-----
 conf/type/__key_value/manifest       | 9 +++------
 2 files changed, 6 insertions(+), 11 deletions(-)

diff --git a/conf/type/__key_value/explorer/value b/conf/type/__key_value/explorer/value
index 3afc7cc5..b4e1fafd 100755
--- a/conf/type/__key_value/explorer/value
+++ b/conf/type/__key_value/explorer/value
@@ -21,11 +21,9 @@
 # Get the current value of key or __NOTSET__ if the key doesn't exist.
 #
 
-if [ -f "$__object/parameter/key" ]; then
-   key="$(cat "$__object/parameter/key")"
-else
-   key="$__object_id"
-fi
+key="$(cat "$__object/parameter/key" 2>/dev/null \
+   || echo "$__object_id")"
+
 file="$(cat "$__object/parameter/file")"
 delimiter="$(cat "$__object/parameter/delimiter")"
 
diff --git a/conf/type/__key_value/manifest b/conf/type/__key_value/manifest
index 706b0b0d..84c06352 100755
--- a/conf/type/__key_value/manifest
+++ b/conf/type/__key_value/manifest
@@ -18,9 +18,6 @@
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
 
-if [ -f "$__object/parameter/key" ]; then
-   key="$(cat "$__object/parameter/key")"
-else
-   echo "$__object_id" > "$__object/parameter/key"
-fi
-
+# set defaults
+[ -f "$__object/parameter/key" ] \
+   || echo "$__object_id" > "$__object/parameter/key"

From cad2097d0559861f66a988c88c4022721fa8c033 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Fri, 3 Feb 2012 22:43:34 +0100
Subject: [PATCH 23/98] complete rewrite: use state explorer to determine
 current state, more robust implementation for adding, changing, removing
 key/values

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 .../__key_value/explorer/{value => state}     | 35 ++++++++----
 conf/type/__key_value/gencode-remote          | 54 +++++++++++--------
 conf/type/__key_value/man.text                | 11 ++--
 conf/type/__key_value/manifest                | 11 +++-
 conf/type/__key_value/parameter/optional      |  2 +
 conf/type/__key_value/parameter/required      |  1 -
 6 files changed, 75 insertions(+), 39 deletions(-)
 rename conf/type/__key_value/explorer/{value => state} (54%)

diff --git a/conf/type/__key_value/explorer/value b/conf/type/__key_value/explorer/state
similarity index 54%
rename from conf/type/__key_value/explorer/value
rename to conf/type/__key_value/explorer/state
index b4e1fafd..7e66cb69 100755
--- a/conf/type/__key_value/explorer/value
+++ b/conf/type/__key_value/explorer/state
@@ -17,19 +17,34 @@
 # You should have received a copy of the GNU General Public License
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
-#
-# Get the current value of key or __NOTSET__ if the key doesn't exist.
-#
 
 key="$(cat "$__object/parameter/key" 2>/dev/null \
    || echo "$__object_id")"
-
+state="$(cat "$__object/parameter/state" 2>/dev/null \
+   || echo "present")"
 file="$(cat "$__object/parameter/file")"
 delimiter="$(cat "$__object/parameter/delimiter")"
+value="$(cat "$__object/parameter/value" 2>/dev/null \
+   || echo "__CDIST_NOTSET__")"
 
-awk -F "$delimiter" '
-BEGIN { found=0 }
-/^'$key'/ { print $2; found=1 }
-END { if (found) exit 0; else exit 1 }' "$file" \
-|| echo "__NOTSET__"
-
+case "$state" in
+   absent)
+      # if the key exists, with whatever value, we will have to remove it
+      # so report it as present
+      if egrep -q "^$key$delimiter+" "$file"; then
+         echo present
+      fi
+   ;;
+   present)
+      if egrep -q "^$key$delimiter+$value$" "$file"; then
+         # key exists and value is same
+         echo present
+      elif egrep -q "^$key$delimiter+" "$file"; then
+         # key exists, but value is empty or different
+         echo wrongvalue
+      else
+         # key does not exist
+         echo absent
+      fi
+   ;;
+esac
diff --git a/conf/type/__key_value/gencode-remote b/conf/type/__key_value/gencode-remote
index 08b3a0f3..0846dca1 100755
--- a/conf/type/__key_value/gencode-remote
+++ b/conf/type/__key_value/gencode-remote
@@ -18,32 +18,40 @@
 # along with cdist. If not, see <http://www.gnu.org/licenses/>.
 #
 
-value_is="$(cat "$__object/explorer/value")"
-value_should="$(cat "$__object/parameter/value")"
-
 key="$(cat "$__object/parameter/key")"
 file="$(cat "$__object/parameter/file")"
 delimiter="$(cat "$__object/parameter/delimiter")"
+value="$(cat "$__object/parameter/value")"
 
-if [ "$value_is" != "$value_should" ]; then
-   case "$value_is" in
-      __NOTSET__)
-         # add key and value
-         echo "echo \"${key}${delimiter}${value_should}\" >> \"$file\""
-      ;;
-      *)
-         if [ "$value_should" = '__NOTSET__' ]; then
-            # remove key and value
-            cat << DONE
-sed -i '/^${key}/d' "$file"
-DONE
-         else
-            # change value
-            cat << DONE
-sed -i "s|^$key\($delimiter\+\).*|$key\1$value_should|" "$file"
-DONE
-         fi
-      ;;
-   esac
+state_is="$(cat "$__object/explorer/state")"
+state_should="$(cat "$__object/parameter/state")"
+
+if [ "$state_is" = "$state_should" ]; then
+   # nothing to do
+   exit 0
 fi
 
+case "$state_should" in
+   absent)
+      # remove lines starting with key
+      echo "sed -i '/^$key\($delimiter\+\)/d' \"$file\""
+   ;;
+   present)
+      case "$state_is" in
+         absent)
+            # add new key and value
+            echo "echo \"${key}${delimiter}${value}\" >> \"$file\""
+         ;;
+         wrongvalue)
+            # change exisiting value
+            echo "sed -i \"s|^$key\($delimiter\+\).*|$key\1$value|\" \"$file\""
+         ;;
+         *)
+            echo "Unknown explorer state: $state_is" >&2
+            exit 1
+      esac
+   ;;
+   *)
+      echo "Unknown state: $state_should" >&2
+      exit 1
+esac 
diff --git a/conf/type/__key_value/man.text b/conf/type/__key_value/man.text
index 3e4e8013..1423fc7d 100644
--- a/conf/type/__key_value/man.text
+++ b/conf/type/__key_value/man.text
@@ -16,9 +16,6 @@ file.
 
 REQUIRED PARAMETERS
 -------------------
-value::
-   The value for the key. Setting the value to `__NOTSET__` will remove the key
-   from the file.
 file::
    The file to operate on.
 delimiter::
@@ -27,8 +24,13 @@ delimiter::
 
 OPTIONAL PARAMETERS
 -------------------
+state::
+   present or absent, defaults to present. If present, sets the key to value,
+   if absent, removes the key from the file.
 key::
    The key to change. Defaults to object_id.
+value::
+   The value for the key. Optional if state=absent, required otherwise.
 
 
 EXAMPLES
@@ -45,6 +47,9 @@ __key_value my-fancy-id --file /etc/login.defs --key SYS_UID_MAX --value 666 \
 # Enable packet forwarding
 __key_value net.ipv4.ip_forward --file /etc/sysctl.conf --value 1 \
    --delimiter '='
+
+# Remove existing key/value
+__key_value LEGACY_KEY --file /etc/somefile --state absent --delimiter '=' 
 --------------------------------------------------------------------------------
 
 
diff --git a/conf/type/__key_value/manifest b/conf/type/__key_value/manifest
index 84c06352..2e75e175 100755
--- a/conf/type/__key_value/manifest
+++ b/conf/type/__key_value/manifest
@@ -19,5 +19,12 @@
 #
 
 # set defaults
-[ -f "$__object/parameter/key" ] \
-   || echo "$__object_id" > "$__object/parameter/key"
+key="$(cat "$__object/parameter/key" 2>/dev/null \
+   || echo "$__object_id" | tee "$__object/parameter/key")"
+state="$(cat "$__object/parameter/state" 2>/dev/null \
+   || echo "present" | tee "$__object/parameter/state")"
+
+if [ "$state" = "present" -a ! -f "$__object/parameter/value" ]; then
+   echo "Missing required parameter 'value'" >&2
+   exit 1
+fi 
diff --git a/conf/type/__key_value/parameter/optional b/conf/type/__key_value/parameter/optional
index 06bfde49..483e3192 100644
--- a/conf/type/__key_value/parameter/optional
+++ b/conf/type/__key_value/parameter/optional
@@ -1 +1,3 @@
 key
+value
+state
diff --git a/conf/type/__key_value/parameter/required b/conf/type/__key_value/parameter/required
index 8f4aa53c..3ae10da3 100644
--- a/conf/type/__key_value/parameter/required
+++ b/conf/type/__key_value/parameter/required
@@ -1,3 +1,2 @@
-value
 file
 delimiter

From ef81f03e89a2b53498f52d2e6262ea0ec94afdd4 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Fri, 3 Feb 2012 22:49:10 +0100
Subject: [PATCH 24/98] have to report absent state no matter what the desired
 state is

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 conf/type/__key_value/explorer/state | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/conf/type/__key_value/explorer/state b/conf/type/__key_value/explorer/state
index 7e66cb69..ec760f71 100755
--- a/conf/type/__key_value/explorer/state
+++ b/conf/type/__key_value/explorer/state
@@ -29,10 +29,13 @@ value="$(cat "$__object/parameter/value" 2>/dev/null \
 
 case "$state" in
    absent)
-      # if the key exists, with whatever value, we will have to remove it
-      # so report it as present
       if egrep -q "^$key$delimiter+" "$file"; then
+         # if the key exists, with whatever value, we will have to remove it
+         # so report it as present
          echo present
+      else
+         # key does not exist
+         echo absent
       fi
    ;;
    present)

From 4d845b3feaf14f413e768256d20983491d9567f9 Mon Sep 17 00:00:00 2001
From: Matt Coddington <coddington@gmail.com>
Date: Tue, 7 Feb 2012 10:27:28 -0500
Subject: [PATCH 25/98] fix for changing a user's group by name

---
 conf/type/__user/gencode-remote | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/conf/type/__user/gencode-remote b/conf/type/__user/gencode-remote
index 595c7f64..077562f4 100755
--- a/conf/type/__user/gencode-remote
+++ b/conf/type/__user/gencode-remote
@@ -28,6 +28,7 @@ cd "$__object/parameter"
 if grep -q "^${name}:" "$__object/explorer/passwd"; then
    for property in $(ls .); do
       new_value="$(cat "$property")"
+      unset current_value
 
       file="$__object/explorer/passwd"
 
@@ -36,9 +37,15 @@ if grep -q "^${name}:" "$__object/explorer/passwd"; then
             if $(echo "$new_value" | grep -q '^[0-9][0-9]*$'); then
                field=4
             else
-               # group name
-               file="$__object/explorer/group"
-               field=1
+               # we were passed a group name.  compare to current gid and
+               # set $current_value to $oldgid if it needs changing.
+               newgid=$(awk -F: '{ print $3 }' "$__object/explorer/group")
+               oldgid=$(awk -F: '{ print $4 }' "$file")
+               if [ "$newgid" != "$oldgid" ]; then
+                  current_value="$oldgid"
+               else
+                  current_value=$new_value
+               fi
             fi
          ;;
          password)
@@ -51,8 +58,10 @@ if grep -q "^${name}:" "$__object/explorer/passwd"; then
          uid)     field=3 ;;
       esac
 
-      export field
-      current_value="$(awk -F: '{ print $ENVIRON["field"] }' < "$file")"
+      if [ -z "$current_value" ]; then
+         export field
+         current_value="$(awk -F: '{ print $ENVIRON["field"] }' < "$file")"
+      fi
 
       if [ "$new_value" != "$current_value" ]; then
          set -- "$@" "--$property" \'$new_value\'

From 908e74689c19c08534cc946949051a4ca11081e0 Mon Sep 17 00:00:00 2001
From: Matt Coddington <coddington@gmail.com>
Date: Tue, 7 Feb 2012 12:38:21 -0500
Subject: [PATCH 26/98] improve comments and use better variable names

---
 conf/type/__user/gencode-remote | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/conf/type/__user/gencode-remote b/conf/type/__user/gencode-remote
index 077562f4..8979c56e 100755
--- a/conf/type/__user/gencode-remote
+++ b/conf/type/__user/gencode-remote
@@ -37,14 +37,15 @@ if grep -q "^${name}:" "$__object/explorer/passwd"; then
             if $(echo "$new_value" | grep -q '^[0-9][0-9]*$'); then
                field=4
             else
-               # we were passed a group name.  compare to current gid and
-               # set $current_value to $oldgid if it needs changing.
-               newgid=$(awk -F: '{ print $3 }' "$__object/explorer/group")
-               oldgid=$(awk -F: '{ print $4 }' "$file")
-               if [ "$newgid" != "$oldgid" ]; then
-                  current_value="$oldgid"
+               # We were passed a group name.  Compare the gid in
+               # the user's /etc/passwd entry with the gid of the
+               # group returned by the group explorer.
+               gid_from_group=$(awk -F: '{ print $3 }' "$__object/explorer/group")
+               gid_from_passwd=$(awk -F: '{ print $4 }' "$file")
+               if [ "$gid_from_group" != "$gid_from_passwd" ]; then
+                  current_value="$gid_from_passwd"
                else
-                  current_value=$new_value
+                  current_value="$new_value"
                fi
             fi
          ;;
@@ -58,6 +59,8 @@ if grep -q "^${name}:" "$__object/explorer/passwd"; then
          uid)     field=3 ;;
       esac
 
+      # If we haven't already set $current_value above, pull it from the
+      # appropriate file/field.
       if [ -z "$current_value" ]; then
          export field
          current_value="$(awk -F: '{ print $ENVIRON["field"] }' < "$file")"

From 817ce9c2562cc24117702a3eac7c3717766d0a87 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Wed, 8 Feb 2012 08:31:59 +0100
Subject: [PATCH 27/98] /egrep/grep -E/

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 conf/type/__key_value/explorer/state | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/conf/type/__key_value/explorer/state b/conf/type/__key_value/explorer/state
index ec760f71..94a5ea7f 100755
--- a/conf/type/__key_value/explorer/state
+++ b/conf/type/__key_value/explorer/state
@@ -29,7 +29,7 @@ value="$(cat "$__object/parameter/value" 2>/dev/null \
 
 case "$state" in
    absent)
-      if egrep -q "^$key$delimiter+" "$file"; then
+      if grep -q -E "^$key$delimiter+" "$file"; then
          # if the key exists, with whatever value, we will have to remove it
          # so report it as present
          echo present
@@ -39,10 +39,10 @@ case "$state" in
       fi
    ;;
    present)
-      if egrep -q "^$key$delimiter+$value$" "$file"; then
+      if grep -q -E "^$key$delimiter+$value$" "$file"; then
          # key exists and value is same
          echo present
-      elif egrep -q "^$key$delimiter+" "$file"; then
+      elif grep -q -E "^$key$delimiter+" "$file"; then
          # key exists, but value is empty or different
          echo wrongvalue
       else

From d55c52601f970deec649f29418d66575be88db66 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Thu, 9 Feb 2012 19:08:32 +0100
Subject: [PATCH 28/98] move run_type_explorer near run_type_explorers

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/explorer.py | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/lib/cdist/core/explorer.py b/lib/cdist/core/explorer.py
index 01c4c81d..43b0339c 100644
--- a/lib/cdist/core/explorer.py
+++ b/lib/cdist/core/explorer.py
@@ -130,6 +130,19 @@ class Explorer(object):
             self.log.debug("Running type explorer '%s' for object '%s'", explorer, cdist_object.name)
             cdist_object.explorers[explorer] = output
 
+    def run_type_explorer(self, explorer, cdist_object):
+        """Run the given type explorer for the given object and return it's output."""
+        cdist_type = cdist_object.type
+        env = self.env.copy()
+        env.update({
+            '__object': os.path.join(self.remote.object_path, cdist_object.path),
+            '__object_id': cdist_object.object_id,
+            '__object_fq': cdist_object.path,
+            '__type_explorer': os.path.join(self.remote.type_path, cdist_type.explorer_path)
+        })
+        script = os.path.join(self.remote.type_path, cdist_type.explorer_path, explorer)
+        return self.remote.run_script(script, env=env, return_output=True)
+
     def transfer_type_explorers(self, cdist_type):
         """Transfer the type explorers for the given type to the remote side."""
         if cdist_type.explorers:
@@ -149,16 +162,3 @@ class Explorer(object):
             destination = os.path.join(self.remote.object_path, cdist_object.parameter_path)
             self.remote.mkdir(destination)
             self.remote.transfer(source, destination)
-
-    def run_type_explorer(self, explorer, cdist_object):
-        """Run the given type explorer for the given object and return it's output."""
-        cdist_type = cdist_object.type
-        env = self.env.copy()
-        env.update({
-            '__object': os.path.join(self.remote.object_path, cdist_object.path),
-            '__object_id': cdist_object.object_id,
-            '__object_fq': cdist_object.path,
-            '__type_explorer': os.path.join(self.remote.type_path, cdist_type.explorer_path)
-        })
-        script = os.path.join(self.remote.type_path, cdist_type.explorer_path, explorer)
-        return self.remote.run_script(script, env=env, return_output=True)

From 1dcc420a38d7fe394e8400704779d2fbb2363a65 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Thu, 9 Feb 2012 19:09:32 +0100
Subject: [PATCH 29/98] no, no common base class for local/remote

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/exec/remote.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/cdist/exec/remote.py b/lib/cdist/exec/remote.py
index 87db7273..b46235a8 100644
--- a/lib/cdist/exec/remote.py
+++ b/lib/cdist/exec/remote.py
@@ -20,8 +20,6 @@
 #
 #
 
-# FIXME: common base class with Local?
-
 import io
 import os
 import sys

From 53c61d42ad659fc6d0f156317c26a3ae34bde071 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Thu, 9 Feb 2012 19:12:49 +0100
Subject: [PATCH 30/98] remove useless if env:

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/exec/remote.py | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/cdist/exec/remote.py b/lib/cdist/exec/remote.py
index b46235a8..69dc5dda 100644
--- a/lib/cdist/exec/remote.py
+++ b/lib/cdist/exec/remote.py
@@ -146,18 +146,17 @@ class Remote(object):
         os_environ = os.environ.copy()
         os_environ['__target_host'] = self.target_host
 
+        self.log.debug("Remote run script: %s", command)
+
         # can't pass environment to remote side, so prepend command with
         # variable declarations
         if env:
+            self.log.debug("Remote run script env: %s", env)
             command.extend(["%s=%s" % item for item in env.items()])
 
         command.extend(["/bin/sh", "-e"])
         command.append(script)
 
-        self.log.debug("Remote run script: %s", command)
-        if env:
-            self.log.debug("Remote run script env: %s", env)
-
         try:
             if return_output:
                 return subprocess.check_output(command, env=os_environ).decode()

From 45053c6d84d0d1693442b6c3f63342042ba4fe83 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Thu, 9 Feb 2012 19:31:30 +0100
Subject: [PATCH 31/98] allow pip to be non existent during explorer stage

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__package_pip/explorer/state | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/conf/type/__package_pip/explorer/state b/conf/type/__package_pip/explorer/state
index 3a086e58..7886a46b 100644
--- a/conf/type/__package_pip/explorer/state
+++ b/conf/type/__package_pip/explorer/state
@@ -35,14 +35,14 @@ else
     pip="pip"
 fi
 
-# which is not posix, but command is :-)
+# If there is no pip, it may get created from somebody else.
+# If it will be created, there is probably no package installed.
 if ! command -v "$pip" >/dev/null 2>&1; then
-    echo "No usable pip found at path \"$pip\"" >&2
-    exit 1
-fi
-
-if "$pip" freeze | grep -i -q "^$name=="; then
-    echo present
-else
     echo absent
+else
+    if "$pip" freeze | grep -i -q "^$name=="; then
+        echo present
+    else
+        echo absent
+    fi
 fi

From 49917d29332558afa7411f1624971cc17c975648 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 10 Feb 2012 13:01:29 +0100
Subject: [PATCH 32/98] +object id issues/ideas

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/logs/2012-02-10.object_id-and-slashes | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 doc/dev/logs/2012-02-10.object_id-and-slashes

diff --git a/doc/dev/logs/2012-02-10.object_id-and-slashes b/doc/dev/logs/2012-02-10.object_id-and-slashes
new file mode 100644
index 00000000..de46a1f8
--- /dev/null
+++ b/doc/dev/logs/2012-02-10.object_id-and-slashes
@@ -0,0 +1,18 @@
+__typename /foo/bar # possible, usual use case
+require="__a//b" __typename /foo/bar # possible and happens often for __a/$id in loops
+
+__typename /foo/bar/ # trailing slash will be stripped, can be documented
+
+__typename /foo//bar//baz # // will be converted to / implicitly through fs; error prone; disallow
+
+require="__a//b//c" __typename # // will be converted to / implicitly through fs; error prone; disallow
+
+
+Solution:
+
+    1) allow require __a//b: type __a, object id /b
+        => strip first slash of object id, as we do in non-dep-mode
+    2) allow _one_ trailing /: __type /foo/bar/ and require="__foo/abc/"
+        => strip one leading slash of object id
+    3) disallow // within object id
+    4) disallow starting or ending / after 1) and 2)

From 947c9a4ccb3a96c2a825a97f40bea4eced22a8e3 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Fri, 10 Feb 2012 16:17:53 +0100
Subject: [PATCH 33/98] ++changes for 2.0.7

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__package_pip/explorer/state | 1 +
 doc/changelog                          | 1 +
 2 files changed, 2 insertions(+)

diff --git a/conf/type/__package_pip/explorer/state b/conf/type/__package_pip/explorer/state
index 7886a46b..5be07280 100644
--- a/conf/type/__package_pip/explorer/state
+++ b/conf/type/__package_pip/explorer/state
@@ -40,6 +40,7 @@ fi
 if ! command -v "$pip" >/dev/null 2>&1; then
     echo absent
 else
+
     if "$pip" freeze | grep -i -q "^$name=="; then
         echo present
     else
diff --git a/doc/changelog b/doc/changelog
index 7e070cc5..dace28dd 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -8,6 +8,7 @@ Changelog
 	* Bugfix __file: Use chmod after chown/chgrp (Matt Coddington)
 	* Bugfix __user: Correct shadow field in explorer (Matt Coddington)
 	* Bugfix __link: Properly handle existing links (Steven Armstrong)
+	* Bugfix __key_value: More robust implementation (Steven Armstrong)
 	* New Type: __package_pip
 
 2.0.6: 2012-01-28

From 2fc2df3a35aefc67ad39f0f0431529970d720049 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sat, 11 Feb 2012 11:53:40 +0100
Subject: [PATCH 34/98] Preperation -> Preparation

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 README | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README b/README
index 51fb323c..965138c4 100644
--- a/README
+++ b/README
@@ -89,7 +89,7 @@ cdist was tested or is know to run on at least
 
 ## Installation
 
-### Preperation
+### Preparation
 
 Ensure you have Python 3.2 installed on the machine you use to **deploy to the targets**
 (the ***source host***).

From 6dcbfc3b88bf7d075801003575f8aec66a943a02 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sun, 12 Feb 2012 00:05:01 +0100
Subject: [PATCH 35/98] more todo

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/niconext | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index 4db98d58..167f124a 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -1,5 +1,14 @@
-- __file/foo/bar//bar
-    - fails later
+- cleanup object_id handling
+    - problems
+        - __file/foo/bar//bar
+            - fails later
+        - right strip __foo/bar/ last slash
+    - only emulator creates objects
+        - strip slashes in object creation?
+    
+
+
+--------------------------------------------------------------------------------
 
 - __user
    add option to include --create-home

From 15fb097464f13f78009a6330c9578b45b102f03c Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sun, 12 Feb 2012 00:05:21 +0100
Subject: [PATCH 36/98] add function to sanitise object_id and verify no //

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/object.py | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/core/object.py b/lib/cdist/core/object.py
index da2f21a6..23e2fba5 100644
--- a/lib/cdist/core/object.py
+++ b/lib/cdist/core/object.py
@@ -105,12 +105,17 @@ class Object(object):
                 raise IllegalObjectIdError(object_id, 'object_id may not start with /')
             if OBJECT_MARKER in object_id.split(os.sep):
                 raise IllegalObjectIdError(object_id, 'object_id may not contain \'%s\'' % OBJECT_MARKER)
+            if '//' in object_id:
+                raise IllegalObjectIdError(object_id, 'object_id may not contain //')
 
     def __init__(self, cdist_type, base_path, object_id=None):
-        self.validate_object_id(object_id)
         self.type = cdist_type # instance of Type
         self.base_path = base_path
         self.object_id = object_id
+
+        self.sanitise_object_id()
+        self.validate_object_id(object_id)
+
         self.name = self.join_name(self.type.name, self.object_id)
         self.path = os.path.join(self.type.path, self.object_id, OBJECT_MARKER)
         self.absolute_path = os.path.join(self.base_path, self.path)
@@ -128,7 +133,6 @@ class Object(object):
     def __hash__(self):
         return hash(self.name)
 
-
     def __lt__(self, other):
         return isinstance(other, self.__class__) and self.name < other.name
 
@@ -146,6 +150,21 @@ class Object(object):
         type_name, object_id = self.split_name(object_name)
         return self.__class__(self.type.__class__(type_path, type_name), base_path, object_id=object_id)
 
+    def sanitise_object_id(self):
+        """
+        Remove leading and trailing slash (one only)
+        """
+
+        print(self.__repr__())
+
+        # Remove leading slash
+        if self.object_id[0] == '/':
+            self.object_id = self.object_id[1:]
+
+        # Remove trailing slash
+        if self.object_id[-1] == '/':
+            self.object_id = self.object_id[:-1]
+
     # FIXME: still needed?
     @property
     def explorer_path(self):

From 4be37f6e9372e0bc338a8c319bba782b84f23090 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sun, 12 Feb 2012 00:08:18 +0100
Subject: [PATCH 37/98] begin rename Object => CdistObject

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/config_install.py         | 12 +++++-----
 lib/cdist/core/object.py            |  8 +++----
 lib/cdist/emulator.py               |  6 ++---
 lib/cdist/test/code/__init__.py     |  2 +-
 lib/cdist/test/emulator/__init__.py |  4 ++--
 lib/cdist/test/explorer/__init__.py |  6 ++---
 lib/cdist/test/manifest/__init__.py |  2 +-
 lib/cdist/test/object/__init__.py   | 34 ++++++++++++++---------------
 lib/cdist/test/resolver/__init__.py |  2 +-
 9 files changed, 37 insertions(+), 39 deletions(-)

diff --git a/lib/cdist/config_install.py b/lib/cdist/config_install.py
index 542f2024..f27fff77 100644
--- a/lib/cdist/config_install.py
+++ b/lib/cdist/config_install.py
@@ -89,9 +89,9 @@ class ConfigInstall(object):
         new_objects_created = True
         while new_objects_created:
             new_objects_created = False
-            for cdist_object in core.Object.list_objects(self.local.object_path,
+            for cdist_object in core.CdistObject.list_objects(self.local.object_path,
                                                          self.local.type_path):
-                if cdist_object.state == core.Object.STATE_PREPARED:
+                if cdist_object.state == core.CdistObject.STATE_PREPARED:
                     self.log.debug("Skipping re-prepare of object %s", cdist_object)
                     continue
                 else:
@@ -103,12 +103,12 @@ class ConfigInstall(object):
         self.log.info("Running manifest and explorers for " + cdist_object.name)
         self.explorer.run_type_explorers(cdist_object)
         self.manifest.run_type_manifest(cdist_object)
-        cdist_object.state = core.Object.STATE_PREPARED
+        cdist_object.state = core.CdistObject.STATE_PREPARED
 
     def object_run(self, cdist_object):
         """Run gencode and code for an object"""
         self.log.debug("Trying to run object " + cdist_object.name)
-        if cdist_object.state == core.Object.STATE_DONE:
+        if cdist_object.state == core.CdistObject.STATE_DONE:
             # TODO: remove once we are sure that this really never happens.
             raise cdist.Error("Attempting to run an already finished object: %s", cdist_object)
 
@@ -130,13 +130,13 @@ class ConfigInstall(object):
 
         # Mark this object as done
         self.log.debug("Finishing run of " + cdist_object.name)
-        cdist_object.state = core.Object.STATE_DONE
+        cdist_object.state = core.CdistObject.STATE_DONE
 
     def stage_run(self):
         """The final (and real) step of deployment"""
         self.log.info("Generating and executing code")
 
-        objects = core.Object.list_objects(
+        objects = core.CdistObject.list_objects(
             self.local.object_path,
             self.local.type_path)
 
diff --git a/lib/cdist/core/object.py b/lib/cdist/core/object.py
index 23e2fba5..278cdc46 100644
--- a/lib/cdist/core/object.py
+++ b/lib/cdist/core/object.py
@@ -42,7 +42,7 @@ class IllegalObjectIdError(cdist.Error):
         return '%s: %s' % (self.message, self.object_id)
 
 
-class Object(object):
+class CdistObject(object):
     """Represents a cdist object.
 
     All interaction with objects in cdist should be done through this class.
@@ -124,7 +124,7 @@ class Object(object):
         self.parameter_path = os.path.join(self.path, "parameter")
 
     def __repr__(self):
-        return '<Object %s>' % self.name
+        return '<CdistObject %s>' % self.name
 
     def __eq__(self, other):
         """define equality as 'name is the same'"""
@@ -142,7 +142,7 @@ class Object(object):
         Mainly intended to create objects when resolving requirements.
 
         e.g:
-            <Object __foo/bar>.object_from_name('__other/object') -> <Object __other/object>
+            <CdistObject __foo/bar>.object_from_name('__other/object') -> <CdistObject __other/object>
 
         """
         type_path = self.type.base_path
@@ -155,8 +155,6 @@ class Object(object):
         Remove leading and trailing slash (one only)
         """
 
-        print(self.__repr__())
-
         # Remove leading slash
         if self.object_id[0] == '/':
             self.object_id = self.object_id[1:]
diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 05202a39..77bc5ac8 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -126,7 +126,7 @@ class Emulator(object):
             self.object_id = self.object_id.lstrip('/')
 
         # Instantiate the cdist object we are defining
-        self.cdist_object = core.Object(self.cdist_type, self.object_base_path, self.object_id)
+        self.cdist_object = core.CdistObject(self.cdist_type, self.object_base_path, self.object_id)
 
         # Create object with given parameters
         self.parameters = {}
@@ -154,13 +154,13 @@ class Emulator(object):
                 if len(requirement) == 0:
                     continue
 
-                requirement_type_name, requirement_object_id = core.Object.split_name(requirement)
+                requirement_type_name, requirement_object_id = core.CdistObject.split_name(requirement)
                 # Instantiate type which fails if type does not exist
                 requirement_type = core.Type(self.type_base_path, requirement_type_name)
 
                 if requirement_object_id:
                     # Validate object_id if any
-                    core.Object.validate_object_id(requirement_object_id)
+                    core.CdistObject.validate_object_id(requirement_object_id)
                 elif not requirement_type.is_singleton:
                     # Only singeltons have no object_id
                     raise IllegalRequirementError(requirement, "Missing object_id and type is not a singleton.")
diff --git a/lib/cdist/test/code/__init__.py b/lib/cdist/test/code/__init__.py
index 2f061086..198d3e95 100644
--- a/lib/cdist/test/code/__init__.py
+++ b/lib/cdist/test/code/__init__.py
@@ -55,7 +55,7 @@ class CodeTestCase(test.CdistTestCase):
         self.code = code.Code(self.target_host, self.local, self.remote)
 
         self.cdist_type = core.Type(self.local.type_path, '__dump_environment')
-        self.cdist_object = core.Object(self.cdist_type, self.local.object_path, 'whatever')
+        self.cdist_object = core.CdistObject(self.cdist_type, self.local.object_path, 'whatever')
         self.cdist_object.create()
 
         self.log = logging.getLogger("cdist")
diff --git a/lib/cdist/test/emulator/__init__.py b/lib/cdist/test/emulator/__init__.py
index e67bed4a..4ea792cb 100644
--- a/lib/cdist/test/emulator/__init__.py
+++ b/lib/cdist/test/emulator/__init__.py
@@ -120,7 +120,7 @@ class AutoRequireEmulatorTestCase(test.CdistTestCase):
         initial_manifest = os.path.join(self.local.manifest_path, "init")
         self.manifest.run_initial_manifest(initial_manifest)
         cdist_type = core.Type(self.local.type_path, '__saturn')
-        cdist_object = core.Object(cdist_type, self.local.object_path, 'singleton')
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'singleton')
         self.manifest.run_type_manifest(cdist_object)
         expected = ['__planet/Saturn', '__moon/Prometheus']
         self.assertEqual(sorted(cdist_object.requirements), sorted(expected))
@@ -157,5 +157,5 @@ class ArgumentsWithDashesTestCase(test.CdistTestCase):
         emu.run()
 
         cdist_type = core.Type(self.local.type_path, '__arguments_with_dashes')
-        cdist_object = core.Object(cdist_type, self.local.object_path, 'some-id')
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'some-id')
         self.assertTrue('with-dash' in cdist_object.parameters)
diff --git a/lib/cdist/test/explorer/__init__.py b/lib/cdist/test/explorer/__init__.py
index cafe34fc..df5a76ab 100644
--- a/lib/cdist/test/explorer/__init__.py
+++ b/lib/cdist/test/explorer/__init__.py
@@ -110,7 +110,7 @@ class ExplorerClassTestCase(test.CdistTestCase):
 
     def test_transfer_object_parameters(self):
         cdist_type = core.Type(self.local.type_path, '__test_type')
-        cdist_object = core.Object(cdist_type, self.local.object_path, 'whatever')
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         cdist_object.create()
         cdist_object.parameters = {'first': 'first value', 'second': 'second value'}
         self.explorer.transfer_object_parameters(cdist_object)
@@ -120,14 +120,14 @@ class ExplorerClassTestCase(test.CdistTestCase):
 
     def test_run_type_explorer(self):
         cdist_type = core.Type(self.local.type_path, '__test_type')
-        cdist_object = core.Object(cdist_type, self.local.object_path, 'whatever')
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         self.explorer.transfer_type_explorers(cdist_type)
         output = self.explorer.run_type_explorer('world', cdist_object)
         self.assertEqual(output, 'hello\n')
 
     def test_run_type_explorers(self):
         cdist_type = core.Type(self.local.type_path, '__test_type')
-        cdist_object = core.Object(cdist_type, self.local.object_path, 'whatever')
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         cdist_object.create()
         self.explorer.run_type_explorers(cdist_object)
         self.assertEqual(cdist_object.explorers, {'world': 'hello'})
diff --git a/lib/cdist/test/manifest/__init__.py b/lib/cdist/test/manifest/__init__.py
index 2383adf7..158cf6fd 100644
--- a/lib/cdist/test/manifest/__init__.py
+++ b/lib/cdist/test/manifest/__init__.py
@@ -80,7 +80,7 @@ class ManifestTestCase(test.CdistTestCase):
 
     def test_type_manifest_environment(self):
         cdist_type = core.Type(self.local.type_path, '__dump_environment')
-        cdist_object = core.Object(cdist_type, self.local.object_path, 'whatever')
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         handle, output_file = self.mkstemp(dir=self.temp_dir)
         os.close(handle)
         os.environ['__cdist_test_out'] = output_file
diff --git a/lib/cdist/test/object/__init__.py b/lib/cdist/test/object/__init__.py
index f199ffb5..9e6f1221 100644
--- a/lib/cdist/test/object/__init__.py
+++ b/lib/cdist/test/object/__init__.py
@@ -34,19 +34,19 @@ type_base_path = op.join(fixtures, 'type')
 class ObjectClassTestCase(test.CdistTestCase):
 
     def test_list_object_names(self):
-        object_names = list(core.Object.list_object_names(object_base_path))
+        object_names = list(core.CdistObject.list_object_names(object_base_path))
         self.assertEqual(object_names, ['__first/man', '__second/on-the', '__third/moon'])
 
     def test_list_type_names(self):
-        type_names = list(core.Object.list_type_names(object_base_path))
+        type_names = list(core.CdistObject.list_type_names(object_base_path))
         self.assertEqual(type_names, ['__first', '__second', '__third'])
 
     def test_list_objects(self):
-        objects = list(core.Object.list_objects(object_base_path, type_base_path))
+        objects = list(core.CdistObject.list_objects(object_base_path, type_base_path))
         objects_expected = [
-            core.Object(core.Type(type_base_path, '__first'), object_base_path, 'man'),
-            core.Object(core.Type(type_base_path, '__second'), object_base_path, 'on-the'),
-            core.Object(core.Type(type_base_path, '__third'), object_base_path, 'moon'),
+            core.CdistObject(core.Type(type_base_path, '__first'), object_base_path, 'man'),
+            core.CdistObject(core.Type(type_base_path, '__second'), object_base_path, 'on-the'),
+            core.CdistObject(core.Type(type_base_path, '__third'), object_base_path, 'moon'),
         ]
         self.assertEqual(objects, objects_expected)
 
@@ -56,18 +56,18 @@ class ObjectIdTestCase(test.CdistTestCase):
         cdist_type = core.Type(type_base_path, '__third')
         illegal_object_id = '/object_id/may/not/start/with/slash'
         with self.assertRaises(core.IllegalObjectIdError):
-            core.Object(cdist_type, object_base_path, illegal_object_id)
+            core.CdistObject(cdist_type, object_base_path, illegal_object_id)
 
     def test_object_id_contains_object_marker(self):
         cdist_type = core.Type(type_base_path, '__third')
         illegal_object_id = 'object_id/may/not/contain/%s/anywhere' % core.OBJECT_MARKER
         with self.assertRaises(core.IllegalObjectIdError):
-            core.Object(cdist_type, object_base_path, illegal_object_id)
+            core.CdistObject(cdist_type, object_base_path, illegal_object_id)
 
     def test_object_id_contains_object_marker_string(self):
         cdist_type = core.Type(type_base_path, '__third')
         illegal_object_id = 'object_id/may/contain_%s_in_filename' % core.OBJECT_MARKER
-        core.Object(cdist_type, object_base_path, illegal_object_id)
+        core.CdistObject(cdist_type, object_base_path, illegal_object_id)
         # if we get here, the test passed
 
 
@@ -75,7 +75,7 @@ class ObjectTestCase(test.CdistTestCase):
 
     def setUp(self):
         self.cdist_type = core.Type(type_base_path, '__third')
-        self.cdist_object = core.Object(self.cdist_type, object_base_path, 'moon') 
+        self.cdist_object = core.CdistObject(self.cdist_type, object_base_path, 'moon') 
 
     def tearDown(self):
         self.cdist_object.changed = False
@@ -159,16 +159,16 @@ class ObjectTestCase(test.CdistTestCase):
         self.assertEqual(self.cdist_object.state, '')
 
     def test_state_prepared(self):
-        self.cdist_object.state = core.Object.STATE_PREPARED
-        self.assertEqual(self.cdist_object.state, core.Object.STATE_PREPARED)
+        self.cdist_object.state = core.CdistObject.STATE_PREPARED
+        self.assertEqual(self.cdist_object.state, core.CdistObject.STATE_PREPARED)
 
     def test_state_running(self):
-        self.cdist_object.state = core.Object.STATE_RUNNING
-        self.assertEqual(self.cdist_object.state, core.Object.STATE_RUNNING)
+        self.cdist_object.state = core.CdistObject.STATE_RUNNING
+        self.assertEqual(self.cdist_object.state, core.CdistObject.STATE_RUNNING)
 
     def test_state_done(self):
-        self.cdist_object.state = core.Object.STATE_DONE
-        self.assertEqual(self.cdist_object.state, core.Object.STATE_DONE)
+        self.cdist_object.state = core.CdistObject.STATE_DONE
+        self.assertEqual(self.cdist_object.state, core.CdistObject.STATE_DONE)
 
     def test_source(self):
         self.assertEqual(list(self.cdist_object.source), [])
@@ -195,6 +195,6 @@ class ObjectTestCase(test.CdistTestCase):
         self.cdist_object.code_remote = 'Hello World'
         other_name = '__first/man'
         other_object = self.cdist_object.object_from_name(other_name)
-        self.assertTrue(isinstance(other_object, core.Object))
+        self.assertTrue(isinstance(other_object, core.CdistObject))
         self.assertEqual(other_object.type.name, '__first')
         self.assertEqual(other_object.object_id, 'man')
diff --git a/lib/cdist/test/resolver/__init__.py b/lib/cdist/test/resolver/__init__.py
index cca058a4..ae8f6915 100644
--- a/lib/cdist/test/resolver/__init__.py
+++ b/lib/cdist/test/resolver/__init__.py
@@ -37,7 +37,7 @@ type_base_path = op.join(fixtures, 'type')
 class ResolverTestCase(test.CdistTestCase):
 
     def setUp(self):
-        self.objects = list(core.Object.list_objects(object_base_path, type_base_path))
+        self.objects = list(core.CdistObject.list_objects(object_base_path, type_base_path))
         self.object_index = dict((o.name, o) for o in self.objects)
         self.dependency_resolver = resolver.DependencyResolver(self.objects)
 

From 1314567012d7394e9b87b7689ccc5080cb0cb981 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sun, 12 Feb 2012 01:10:57 +0100
Subject: [PATCH 38/98] also begin to prefix type with cdist

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/__init__.py                    | 16 ++++++++--------
 lib/cdist/core/{object.py => cdist_object.py} |  0
 lib/cdist/core/{type.py => cdist_type.py}     |  6 +++---
 lib/cdist/test/object/__init__.py             |  2 +-
 4 files changed, 12 insertions(+), 12 deletions(-)
 rename lib/cdist/core/{object.py => cdist_object.py} (100%)
 rename lib/cdist/core/{type.py => cdist_type.py} (97%)

diff --git a/lib/cdist/core/__init__.py b/lib/cdist/core/__init__.py
index c61c659b..66ee00a5 100644
--- a/lib/cdist/core/__init__.py
+++ b/lib/cdist/core/__init__.py
@@ -19,11 +19,11 @@
 #
 #
 
-from cdist.core.type import Type
-from cdist.core.type import NoSuchTypeError
-from cdist.core.object import Object
-from cdist.core.object import IllegalObjectIdError
-from cdist.core.object import OBJECT_MARKER
-from cdist.core.explorer import Explorer
-from cdist.core.manifest import Manifest
-from cdist.core.code import Code
+from cdist.core.cdist_type      import CdistType
+from cdist.core.cdist_type      import NoSuchTypeError
+from cdist.core.cdist_object    import CdistObject
+from cdist.core.cdist_object    import IllegalObjectIdError
+from cdist.core.cdist_object    import OBJECT_MARKER
+from cdist.core.explorer        import Explorer
+from cdist.core.manifest        import Manifest
+from cdist.core.code            import Code
diff --git a/lib/cdist/core/object.py b/lib/cdist/core/cdist_object.py
similarity index 100%
rename from lib/cdist/core/object.py
rename to lib/cdist/core/cdist_object.py
diff --git a/lib/cdist/core/type.py b/lib/cdist/core/cdist_type.py
similarity index 97%
rename from lib/cdist/core/type.py
rename to lib/cdist/core/cdist_type.py
index 20365b8d..55609e7e 100644
--- a/lib/cdist/core/type.py
+++ b/lib/cdist/core/cdist_type.py
@@ -34,7 +34,7 @@ class NoSuchTypeError(cdist.Error):
         return "Type '%s' does not exist at %s" % (self.type_path, self.type_absolute_path)
 
 
-class Type(object):
+class CdistType(object):
     """Represents a cdist type.
 
     All interaction with types in cdist should be done through this class.
@@ -61,7 +61,7 @@ class Type(object):
         # name is second argument
         name = args[1]
         if not name in cls._instances:
-            instance = super(Type, cls).__new__(cls)
+            instance = super(CdistType, cls).__new__(cls)
             cls._instances[name] = instance
             # return instance so __init__ is called
         return cls._instances[name]
@@ -84,7 +84,7 @@ class Type(object):
         self.__optional_parameters = None
 
     def __repr__(self):
-        return '<Type %s>' % self.name
+        return '<CdistType %s>' % self.name
 
     def __eq__(self, other):
         return isinstance(other, self.__class__) and self.name == other.name
diff --git a/lib/cdist/test/object/__init__.py b/lib/cdist/test/object/__init__.py
index 9e6f1221..a633955a 100644
--- a/lib/cdist/test/object/__init__.py
+++ b/lib/cdist/test/object/__init__.py
@@ -38,7 +38,7 @@ class ObjectClassTestCase(test.CdistTestCase):
         self.assertEqual(object_names, ['__first/man', '__second/on-the', '__third/moon'])
 
     def test_list_type_names(self):
-        type_names = list(core.CdistObject.list_type_names(object_base_path))
+        type_names = list(cdist.core.CdistObject.list_type_names(object_base_path))
         self.assertEqual(type_names, ['__first', '__second', '__third'])
 
     def test_list_objects(self):

From fb4f8784b6cb0cdd83aa6fe109bcddcd884967f2 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sun, 12 Feb 2012 01:18:14 +0100
Subject: [PATCH 39/98] rename Type => CdistType

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py      |  2 +-
 lib/cdist/test/code/__init__.py     |  6 ++--
 lib/cdist/test/emulator/__init__.py |  4 +--
 lib/cdist/test/explorer/__init__.py | 18 +++++-----
 lib/cdist/test/manifest/__init__.py |  2 +-
 lib/cdist/test/object/__init__.py   | 14 ++++----
 lib/cdist/test/type/__init__.py     | 52 ++++++++++++++---------------
 7 files changed, 50 insertions(+), 48 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index 278cdc46..43d07d6b 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -61,7 +61,7 @@ class CdistObject(object):
         """Return a list of object instances"""
         for object_name in cls.list_object_names(object_base_path):
             type_name, object_id = cls.split_name(object_name)
-            yield cls(cdist.core.Type(type_base_path, type_name), object_base_path, object_id=object_id)
+            yield cls(cdist.core.CdistType(type_base_path, type_name), object_base_path, object_id=object_id)
 
     @classmethod
     def list_type_names(cls, object_base_path):
diff --git a/lib/cdist/test/code/__init__.py b/lib/cdist/test/code/__init__.py
index 198d3e95..176f139c 100644
--- a/lib/cdist/test/code/__init__.py
+++ b/lib/cdist/test/code/__init__.py
@@ -48,13 +48,13 @@ class CodeTestCase(test.CdistTestCase):
 
         self.remote_base_path = self.mkdtemp()
         self.user = getpass.getuser()
-        remote_exec = "ssh -o User=%s -q" % self.user
-        remote_copy = "scp -o User=%s -q" % self.user
+        remote_exec = "ssh -o User=%s -q" % "root" # self.user
+        remote_copy = "scp -o User=%s -q" % "root" # self.user
         self.remote = remote.Remote(self.target_host, self.remote_base_path, remote_exec, remote_copy)
 
         self.code = code.Code(self.target_host, self.local, self.remote)
 
-        self.cdist_type = core.Type(self.local.type_path, '__dump_environment')
+        self.cdist_type = core.CdistType(self.local.type_path, '__dump_environment')
         self.cdist_object = core.CdistObject(self.cdist_type, self.local.object_path, 'whatever')
         self.cdist_object.create()
 
diff --git a/lib/cdist/test/emulator/__init__.py b/lib/cdist/test/emulator/__init__.py
index 4ea792cb..c0037b68 100644
--- a/lib/cdist/test/emulator/__init__.py
+++ b/lib/cdist/test/emulator/__init__.py
@@ -119,7 +119,7 @@ class AutoRequireEmulatorTestCase(test.CdistTestCase):
     def test_autorequire(self):
         initial_manifest = os.path.join(self.local.manifest_path, "init")
         self.manifest.run_initial_manifest(initial_manifest)
-        cdist_type = core.Type(self.local.type_path, '__saturn')
+        cdist_type = core.CdistType(self.local.type_path, '__saturn')
         cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'singleton')
         self.manifest.run_type_manifest(cdist_object)
         expected = ['__planet/Saturn', '__moon/Prometheus']
@@ -156,6 +156,6 @@ class ArgumentsWithDashesTestCase(test.CdistTestCase):
         emu = emulator.Emulator(argv)
         emu.run()
 
-        cdist_type = core.Type(self.local.type_path, '__arguments_with_dashes')
+        cdist_type = core.CdistType(self.local.type_path, '__arguments_with_dashes')
         cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'some-id')
         self.assertTrue('with-dash' in cdist_object.parameters)
diff --git a/lib/cdist/test/explorer/__init__.py b/lib/cdist/test/explorer/__init__.py
index df5a76ab..716e56b7 100644
--- a/lib/cdist/test/explorer/__init__.py
+++ b/lib/cdist/test/explorer/__init__.py
@@ -49,8 +49,10 @@ class ExplorerClassTestCase(test.CdistTestCase):
 
         self.remote_base_path = self.mkdtemp()
         self.user = getpass.getuser()
-        remote_exec = "ssh -o User=%s -q" % self.user
-        remote_copy = "scp -o User=%s -q" % self.user
+        #remote_exec = "ssh -o User=%s -q" % self.user
+        #remote_copy = "scp -o User=%s -q" % self.user
+        remote_exec = "ssh -o User=%s -q" % "root"
+        remote_copy = "scp -o User=%s -q" % "root"
         self.remote = remote.Remote(self.target_host, self.remote_base_path, remote_exec, remote_copy)
 
         self.explorer = explorer.Explorer(self.target_host, self.local, self.remote)
@@ -83,19 +85,19 @@ class ExplorerClassTestCase(test.CdistTestCase):
         shutil.rmtree(out_path)
 
     def test_list_type_explorer_names(self):
-        cdist_type = core.Type(self.local.type_path, '__test_type')
+        cdist_type = core.CdistType(self.local.type_path, '__test_type')
         expected = cdist_type.explorers
         self.assertEqual(self.explorer.list_type_explorer_names(cdist_type), expected)
 
     def test_transfer_type_explorers(self):
-        cdist_type = core.Type(self.local.type_path, '__test_type')
+        cdist_type = core.CdistType(self.local.type_path, '__test_type')
         self.explorer.transfer_type_explorers(cdist_type)
         source = os.path.join(self.local.type_path, cdist_type.explorer_path)
         destination = os.path.join(self.remote.type_path, cdist_type.explorer_path)
         self.assertEqual(os.listdir(source), os.listdir(destination))
 
     def test_transfer_type_explorers_only_once(self):
-        cdist_type = core.Type(self.local.type_path, '__test_type')
+        cdist_type = core.CdistType(self.local.type_path, '__test_type')
         # first transfer
         self.explorer.transfer_type_explorers(cdist_type)
         source = os.path.join(self.local.type_path, cdist_type.explorer_path)
@@ -109,7 +111,7 @@ class ExplorerClassTestCase(test.CdistTestCase):
         self.assertFalse(os.listdir(destination))
 
     def test_transfer_object_parameters(self):
-        cdist_type = core.Type(self.local.type_path, '__test_type')
+        cdist_type = core.CdistType(self.local.type_path, '__test_type')
         cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         cdist_object.create()
         cdist_object.parameters = {'first': 'first value', 'second': 'second value'}
@@ -119,14 +121,14 @@ class ExplorerClassTestCase(test.CdistTestCase):
         self.assertEqual(sorted(os.listdir(source)), sorted(os.listdir(destination)))
 
     def test_run_type_explorer(self):
-        cdist_type = core.Type(self.local.type_path, '__test_type')
+        cdist_type = core.CdistType(self.local.type_path, '__test_type')
         cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         self.explorer.transfer_type_explorers(cdist_type)
         output = self.explorer.run_type_explorer('world', cdist_object)
         self.assertEqual(output, 'hello\n')
 
     def test_run_type_explorers(self):
-        cdist_type = core.Type(self.local.type_path, '__test_type')
+        cdist_type = core.CdistType(self.local.type_path, '__test_type')
         cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         cdist_object.create()
         self.explorer.run_type_explorers(cdist_object)
diff --git a/lib/cdist/test/manifest/__init__.py b/lib/cdist/test/manifest/__init__.py
index 158cf6fd..a188c788 100644
--- a/lib/cdist/test/manifest/__init__.py
+++ b/lib/cdist/test/manifest/__init__.py
@@ -79,7 +79,7 @@ class ManifestTestCase(test.CdistTestCase):
         self.assertEqual(output_dict['__manifest'], self.local.manifest_path)
 
     def test_type_manifest_environment(self):
-        cdist_type = core.Type(self.local.type_path, '__dump_environment')
+        cdist_type = core.CdistType(self.local.type_path, '__dump_environment')
         cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'whatever')
         handle, output_file = self.mkstemp(dir=self.temp_dir)
         os.close(handle)
diff --git a/lib/cdist/test/object/__init__.py b/lib/cdist/test/object/__init__.py
index a633955a..00cc1e00 100644
--- a/lib/cdist/test/object/__init__.py
+++ b/lib/cdist/test/object/__init__.py
@@ -44,28 +44,28 @@ class ObjectClassTestCase(test.CdistTestCase):
     def test_list_objects(self):
         objects = list(core.CdistObject.list_objects(object_base_path, type_base_path))
         objects_expected = [
-            core.CdistObject(core.Type(type_base_path, '__first'), object_base_path, 'man'),
-            core.CdistObject(core.Type(type_base_path, '__second'), object_base_path, 'on-the'),
-            core.CdistObject(core.Type(type_base_path, '__third'), object_base_path, 'moon'),
+            core.CdistObject(core.CdistType(type_base_path, '__first'), object_base_path, 'man'),
+            core.CdistObject(core.CdistType(type_base_path, '__second'), object_base_path, 'on-the'),
+            core.CdistObject(core.CdistType(type_base_path, '__third'), object_base_path, 'moon'),
         ]
         self.assertEqual(objects, objects_expected)
 
 
 class ObjectIdTestCase(test.CdistTestCase):
     def test_object_id_starts_with_slash(self):
-        cdist_type = core.Type(type_base_path, '__third')
+        cdist_type = core.CdistType(type_base_path, '__third')
         illegal_object_id = '/object_id/may/not/start/with/slash'
         with self.assertRaises(core.IllegalObjectIdError):
             core.CdistObject(cdist_type, object_base_path, illegal_object_id)
 
     def test_object_id_contains_object_marker(self):
-        cdist_type = core.Type(type_base_path, '__third')
+        cdist_type = core.CdistType(type_base_path, '__third')
         illegal_object_id = 'object_id/may/not/contain/%s/anywhere' % core.OBJECT_MARKER
         with self.assertRaises(core.IllegalObjectIdError):
             core.CdistObject(cdist_type, object_base_path, illegal_object_id)
 
     def test_object_id_contains_object_marker_string(self):
-        cdist_type = core.Type(type_base_path, '__third')
+        cdist_type = core.CdistType(type_base_path, '__third')
         illegal_object_id = 'object_id/may/contain_%s_in_filename' % core.OBJECT_MARKER
         core.CdistObject(cdist_type, object_base_path, illegal_object_id)
         # if we get here, the test passed
@@ -74,7 +74,7 @@ class ObjectIdTestCase(test.CdistTestCase):
 class ObjectTestCase(test.CdistTestCase):
 
     def setUp(self):
-        self.cdist_type = core.Type(type_base_path, '__third')
+        self.cdist_type = core.CdistType(type_base_path, '__third')
         self.cdist_object = core.CdistObject(self.cdist_type, object_base_path, 'moon') 
 
     def tearDown(self):
diff --git a/lib/cdist/test/type/__init__.py b/lib/cdist/test/type/__init__.py
index 7bb8654c..2ef14a4c 100644
--- a/lib/cdist/test/type/__init__.py
+++ b/lib/cdist/test/type/__init__.py
@@ -33,115 +33,115 @@ class TypeTestCase(test.CdistTestCase):
 
     def test_list_type_names(self):
         base_path = op.join(fixtures, 'list_types')
-        type_names = core.Type.list_type_names(base_path)
+        type_names = core.CdistType.list_type_names(base_path)
         self.assertEqual(type_names, ['__first', '__second', '__third'])
 
     def test_list_types(self):
         base_path = op.join(fixtures, 'list_types')
-        types = list(core.Type.list_types(base_path))
+        types = list(core.CdistType.list_types(base_path))
         types_expected = [
-            core.Type(base_path, '__first'),
-            core.Type(base_path, '__second'),
-            core.Type(base_path, '__third'),
+            core.CdistType(base_path, '__first'),
+            core.CdistType(base_path, '__second'),
+            core.CdistType(base_path, '__third'),
         ]
         self.assertEqual(types, types_expected)
 
     def test_only_one_instance(self):
         base_path = fixtures
-        cdist_type1 = core.Type(base_path, '__name_path')
-        cdist_type2 = core.Type(base_path, '__name_path')
+        cdist_type1 = core.CdistType(base_path, '__name_path')
+        cdist_type2 = core.CdistType(base_path, '__name_path')
         self.assertEqual(id(cdist_type1), id(cdist_type2))
 
     def test_nonexistent_type(self):
         base_path = fixtures
-        self.assertRaises(core.NoSuchTypeError, core.Type, base_path, '__i-dont-exist')
+        self.assertRaises(core.NoSuchTypeError, core.CdistType, base_path, '__i-dont-exist')
 
     def test_name(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.name, '__name_path')
 
     def test_path(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.path, '__name_path')
 
     def test_base_path(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.base_path, base_path)
 
     def test_absolute_path(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.absolute_path, os.path.join(base_path, '__name_path'))
 
     def test_manifest_path(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.manifest_path, os.path.join('__name_path', 'manifest'))
 
     def test_explorer_path(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.explorer_path, os.path.join('__name_path', 'explorer'))
 
     def test_gencode_local_path(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.gencode_local_path, os.path.join('__name_path', 'gencode-local'))
 
     def test_gencode_remote_path(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__name_path')
+        cdist_type = core.CdistType(base_path, '__name_path')
         self.assertEqual(cdist_type.gencode_remote_path, os.path.join('__name_path', 'gencode-remote'))
 
     def test_singleton_is_singleton(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__singleton')
+        cdist_type = core.CdistType(base_path, '__singleton')
         self.assertTrue(cdist_type.is_singleton)
 
     def test_not_singleton_is_singleton(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__not_singleton')
+        cdist_type = core.CdistType(base_path, '__not_singleton')
         self.assertFalse(cdist_type.is_singleton)
 
     def test_install_is_install(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__install')
+        cdist_type = core.CdistType(base_path, '__install')
         self.assertTrue(cdist_type.is_install)
 
     def test_not_install_is_install(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__not_install')
+        cdist_type = core.CdistType(base_path, '__not_install')
         self.assertFalse(cdist_type.is_install)
 
     def test_with_explorers(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__with_explorers')
+        cdist_type = core.CdistType(base_path, '__with_explorers')
         self.assertEqual(cdist_type.explorers, ['whatever'])
 
     def test_without_explorers(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__without_explorers')
+        cdist_type = core.CdistType(base_path, '__without_explorers')
         self.assertEqual(cdist_type.explorers, [])
 
     def test_with_required_parameters(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__with_required_parameters')
+        cdist_type = core.CdistType(base_path, '__with_required_parameters')
         self.assertEqual(cdist_type.required_parameters, ['required1', 'required2'])
 
     def test_without_required_parameters(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__without_required_parameters')
+        cdist_type = core.CdistType(base_path, '__without_required_parameters')
         self.assertEqual(cdist_type.required_parameters, [])
 
     def test_with_optional_parameters(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__with_optional_parameters')
+        cdist_type = core.CdistType(base_path, '__with_optional_parameters')
         self.assertEqual(cdist_type.optional_parameters, ['optional1', 'optional2'])
 
     def test_without_optional_parameters(self):
         base_path = fixtures
-        cdist_type = core.Type(base_path, '__without_optional_parameters')
+        cdist_type = core.CdistType(base_path, '__without_optional_parameters')
         self.assertEqual(cdist_type.optional_parameters, [])

From 91ecfa7d3f185e4baab2d5a3e903924d4170c026 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Sun, 12 Feb 2012 01:27:25 +0100
Subject: [PATCH 40/98] back to 100% tests working

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/emulator.py               | 8 +++++---
 lib/cdist/exec/local.py             | 2 +-
 lib/cdist/test/code/__init__.py     | 4 ++--
 lib/cdist/test/explorer/__init__.py | 6 ++----
 lib/cdist/test/object/__init__.py   | 2 ++
 5 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 77bc5ac8..72ed3b9b 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -41,14 +41,16 @@ class Emulator(object):
         self.object_id      = False
 
         self.global_path    = os.environ['__global']
-        self.object_source  = os.environ['__cdist_manifest']
         self.target_host    = os.environ['__target_host']
+
+        # Internally only
+        self.object_source  = os.environ['__cdist_manifest']
         self.type_base_path = os.environ['__cdist_type_base_path']
 
         self.object_base_path = os.path.join(self.global_path, "object")
 
         self.type_name      = os.path.basename(argv[0])
-        self.cdist_type     = core.Type(self.type_base_path, self.type_name)
+        self.cdist_type     = core.CdistType(self.type_base_path, self.type_name)
 
         self.__init_log()
 
@@ -156,7 +158,7 @@ class Emulator(object):
 
                 requirement_type_name, requirement_object_id = core.CdistObject.split_name(requirement)
                 # Instantiate type which fails if type does not exist
-                requirement_type = core.Type(self.type_base_path, requirement_type_name)
+                requirement_type = core.CdistType(self.type_base_path, requirement_type_name)
 
                 if requirement_object_id:
                     # Validate object_id if any
diff --git a/lib/cdist/exec/local.py b/lib/cdist/exec/local.py
index 613f5cf2..cdf06205 100644
--- a/lib/cdist/exec/local.py
+++ b/lib/cdist/exec/local.py
@@ -143,7 +143,7 @@ class Local(object):
     def link_emulator(self, exec_path):
         """Link emulator to types"""
         src = os.path.abspath(exec_path)
-        for cdist_type in core.Type.list_types(self.type_path):
+        for cdist_type in core.CdistType.list_types(self.type_path):
             dst = os.path.join(self.bin_path, cdist_type.name)
             self.log.debug("Linking emulator: %s to %s", src, dst)
 
diff --git a/lib/cdist/test/code/__init__.py b/lib/cdist/test/code/__init__.py
index 176f139c..dc701cce 100644
--- a/lib/cdist/test/code/__init__.py
+++ b/lib/cdist/test/code/__init__.py
@@ -48,8 +48,8 @@ class CodeTestCase(test.CdistTestCase):
 
         self.remote_base_path = self.mkdtemp()
         self.user = getpass.getuser()
-        remote_exec = "ssh -o User=%s -q" % "root" # self.user
-        remote_copy = "scp -o User=%s -q" % "root" # self.user
+        remote_exec = "ssh -o User=%s -q" % self.user
+        remote_copy = "scp -o User=%s -q" % self.user
         self.remote = remote.Remote(self.target_host, self.remote_base_path, remote_exec, remote_copy)
 
         self.code = code.Code(self.target_host, self.local, self.remote)
diff --git a/lib/cdist/test/explorer/__init__.py b/lib/cdist/test/explorer/__init__.py
index 716e56b7..257ad8a9 100644
--- a/lib/cdist/test/explorer/__init__.py
+++ b/lib/cdist/test/explorer/__init__.py
@@ -49,10 +49,8 @@ class ExplorerClassTestCase(test.CdistTestCase):
 
         self.remote_base_path = self.mkdtemp()
         self.user = getpass.getuser()
-        #remote_exec = "ssh -o User=%s -q" % self.user
-        #remote_copy = "scp -o User=%s -q" % self.user
-        remote_exec = "ssh -o User=%s -q" % "root"
-        remote_copy = "scp -o User=%s -q" % "root"
+        remote_exec = "ssh -o User=%s -q" % self.user
+        remote_copy = "scp -o User=%s -q" % self.user
         self.remote = remote.Remote(self.target_host, self.remote_base_path, remote_exec, remote_copy)
 
         self.explorer = explorer.Explorer(self.target_host, self.local, self.remote)
diff --git a/lib/cdist/test/object/__init__.py b/lib/cdist/test/object/__init__.py
index 00cc1e00..0f8c0189 100644
--- a/lib/cdist/test/object/__init__.py
+++ b/lib/cdist/test/object/__init__.py
@@ -25,6 +25,8 @@ import shutil
 from cdist import test
 from cdist import core
 
+import cdist
+
 import os.path as op
 my_dir = op.abspath(op.dirname(__file__))
 fixtures = op.join(my_dir, 'fixtures')

From 0c990e17566bc86fbcdade68fcbbcb3eff450a5f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 07:25:04 +0100
Subject: [PATCH 41/98] add singleton / no object_id test to CdistObject

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 16 ++++++++++------
 1 file changed, 10 insertions(+), 6 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index 43d07d6b..6b1e02b0 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -96,25 +96,29 @@ class CdistObject(object):
         """
         return os.path.join(type_name, object_id)
 
-    @staticmethod
-    def validate_object_id(object_id):
+    def validate_object_id(self):
         """Validate the given object_id and raise IllegalObjectIdError if it's not valid.
         """
         if object_id:
-            if object_id.startswith('/'):
+            if self.object_id.startswith('/'):
                 raise IllegalObjectIdError(object_id, 'object_id may not start with /')
-            if OBJECT_MARKER in object_id.split(os.sep):
+            if OBJECT_MARKER in self.object_id.split(os.sep):
                 raise IllegalObjectIdError(object_id, 'object_id may not contain \'%s\'' % OBJECT_MARKER)
-            if '//' in object_id:
+            if '//' in self.object_id:
                 raise IllegalObjectIdError(object_id, 'object_id may not contain //')
 
+        # If no object_id and type is not singleton => error out
+        if not object_id and not self.type.is_singleton:
+            raise IllegalObjectIdError(object_id,
+                "Missing object_id and type is not a singleton.")
+
     def __init__(self, cdist_type, base_path, object_id=None):
         self.type = cdist_type # instance of Type
         self.base_path = base_path
         self.object_id = object_id
 
         self.sanitise_object_id()
-        self.validate_object_id(object_id)
+        self.validate_object_id()
 
         self.name = self.join_name(self.type.name, self.object_id)
         self.path = os.path.join(self.type.path, self.object_id, OBJECT_MARKER)

From ab565dc3d90e8f2de14976e0e902bc52e3669af0 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 07:45:10 +0100
Subject: [PATCH 42/98] cleanup / emulator

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/niconext | 12 ++++--------
 lib/cdist/emulator.py | 17 ++++-------------
 2 files changed, 8 insertions(+), 21 deletions(-)

diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index 167f124a..34c2f7b0 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -1,12 +1,8 @@
 - cleanup object_id handling
-    - problems
-        - __file/foo/bar//bar
-            - fails later
-        - right strip __foo/bar/ last slash
-    - only emulator creates objects
-        - strip slashes in object creation?
-    
-
+    - have a look at singletons
+    - double check verification
+    - cleanup emulator to create object
+    - adjust tests
 
 --------------------------------------------------------------------------------
 
diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 72ed3b9b..67f6d373 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -115,18 +115,13 @@ class Emulator(object):
 
 
     def setup_object(self):
-        # FIXME: verify object id
-
-        # Setup object_id
+        # Setup object_id - FIXME: unset / do not setup anymore!
         if self.cdist_type.is_singleton:
             self.object_id = "singleton"
         else:
             self.object_id = self.args.object_id[0]
             del self.args.object_id
 
-            # strip leading slash from object_id
-            self.object_id = self.object_id.lstrip('/')
-
         # Instantiate the cdist object we are defining
         self.cdist_object = core.CdistObject(self.cdist_type, self.object_base_path, self.object_id)
 
@@ -160,13 +155,9 @@ class Emulator(object):
                 # Instantiate type which fails if type does not exist
                 requirement_type = core.CdistType(self.type_base_path, requirement_type_name)
 
-                if requirement_object_id:
-                    # Validate object_id if any
-                    core.CdistObject.validate_object_id(requirement_object_id)
-                elif not requirement_type.is_singleton:
-                    # Only singeltons have no object_id
-                    raise IllegalRequirementError(requirement, "Missing object_id and type is not a singleton.")
-
+                # FIXME: need try/catch here or pass exception from core.CdistObject?
+                # Instantiate object, which fails if object id is broken
+                requirement_object = core.CdistObject(requirement_type, self.object_base_path, requirement_object_id)
                 self.log.debug("Recording requirement: " + requirement)
                 self.cdist_object.requirements.append(requirement)
 

From f27730e10b374a1952b825cb874b7089fb12acbf Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 07:45:32 +0100
Subject: [PATCH 43/98] finish rewrite to instance method

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 42 ++++++++++++++++++----------------
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index 6b1e02b0..81b7e7e9 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -97,19 +97,21 @@ class CdistObject(object):
         return os.path.join(type_name, object_id)
 
     def validate_object_id(self):
+        # FIXME: also check that there is no object ID when type is singleton?
+
         """Validate the given object_id and raise IllegalObjectIdError if it's not valid.
         """
-        if object_id:
+        if self.object_id:
             if self.object_id.startswith('/'):
-                raise IllegalObjectIdError(object_id, 'object_id may not start with /')
+                raise IllegalObjectIdError(self.object_id, 'object_id may not start with /')
             if OBJECT_MARKER in self.object_id.split(os.sep):
-                raise IllegalObjectIdError(object_id, 'object_id may not contain \'%s\'' % OBJECT_MARKER)
+                raise IllegalObjectIdError(self.object_id, 'object_id may not contain \'%s\'' % OBJECT_MARKER)
             if '//' in self.object_id:
-                raise IllegalObjectIdError(object_id, 'object_id may not contain //')
+                raise IllegalObjectIdError(self.object_id, 'object_id may not contain //')
 
         # If no object_id and type is not singleton => error out
-        if not object_id and not self.type.is_singleton:
-            raise IllegalObjectIdError(object_id,
+        if not self.object_id and not self.type.is_singleton:
+            raise IllegalObjectIdError(self.object_id,
                 "Missing object_id and type is not a singleton.")
 
     def __init__(self, cdist_type, base_path, object_id=None):
@@ -127,19 +129,6 @@ class CdistObject(object):
         self.code_remote_path = os.path.join(self.path, "code-remote")
         self.parameter_path = os.path.join(self.path, "parameter")
 
-    def __repr__(self):
-        return '<CdistObject %s>' % self.name
-
-    def __eq__(self, other):
-        """define equality as 'name is the same'"""
-        return self.name == other.name
-    
-    def __hash__(self):
-        return hash(self.name)
-
-    def __lt__(self, other):
-        return isinstance(other, self.__class__) and self.name < other.name
-
     def object_from_name(self, object_name):
         """Convenience method for creating an object instance from an object name.
 
@@ -154,7 +143,20 @@ class CdistObject(object):
         type_name, object_id = self.split_name(object_name)
         return self.__class__(self.type.__class__(type_path, type_name), base_path, object_id=object_id)
 
-    def sanitise_object_id(self):
+     def __repr__(self):
+        return '<CdistObject %s>' % self.name
+
+    def __eq__(self, other):
+        """define equality as 'name is the same'"""
+        return self.name == other.name
+    
+    def __hash__(self):
+        return hash(self.name)
+
+    def __lt__(self, other):
+        return isinstance(other, self.__class__) and self.name < other.name
+
+   def sanitise_object_id(self):
         """
         Remove leading and trailing slash (one only)
         """

From 754aba1a15fcee312308fcd54d3757fdae195b59 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 07:47:33 +0100
Subject: [PATCH 44/98] record source in setup_object not in requirements

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/emulator.py | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 67f6d373..8174b38f 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -140,6 +140,9 @@ class Emulator(object):
             self.cdist_object.create()
             self.cdist_object.parameters = self.parameters
 
+        # Record / Append source
+        self.cdist_object.source.append(self.object_source)
+
     def record_requirements(self):
         """record requirements"""
 
@@ -153,17 +156,16 @@ class Emulator(object):
 
                 requirement_type_name, requirement_object_id = core.CdistObject.split_name(requirement)
                 # Instantiate type which fails if type does not exist
-                requirement_type = core.CdistType(self.type_base_path, requirement_type_name)
+                requirement_type = core.CdistType(self.type_base_path,
+                    requirement_type_name)
 
-                # FIXME: need try/catch here or pass exception from core.CdistObject?
                 # Instantiate object, which fails if object id is broken
-                requirement_object = core.CdistObject(requirement_type, self.object_base_path, requirement_object_id)
+                requirement_object = core.CdistObject(requirement_type,
+                    self.object_base_path, requirement_object_id)
+
                 self.log.debug("Recording requirement: " + requirement)
                 self.cdist_object.requirements.append(requirement)
 
-        # Record / Append source
-        self.cdist_object.source.append(self.object_source)
-
     def record_auto_requirements(self):
         """An object shall automatically depend on all objects that it defined in it's type manifest.
         """

From 097b4ea6ada2bd55c0750429218a43871b80f413 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 07:50:11 +0100
Subject: [PATCH 45/98] :%s/self.type/self.cdist_type/g

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index 81b7e7e9..e7ea7a9f 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -110,20 +110,20 @@ class CdistObject(object):
                 raise IllegalObjectIdError(self.object_id, 'object_id may not contain //')
 
         # If no object_id and type is not singleton => error out
-        if not self.object_id and not self.type.is_singleton:
+        if not self.object_id and not self.cdist_type.is_singleton:
             raise IllegalObjectIdError(self.object_id,
                 "Missing object_id and type is not a singleton.")
 
     def __init__(self, cdist_type, base_path, object_id=None):
-        self.type = cdist_type # instance of Type
+        self.cdist_type = cdist_type # instance of Type
         self.base_path = base_path
         self.object_id = object_id
 
         self.sanitise_object_id()
         self.validate_object_id()
 
-        self.name = self.join_name(self.type.name, self.object_id)
-        self.path = os.path.join(self.type.path, self.object_id, OBJECT_MARKER)
+        self.name = self.join_name(self.cdist_type.name, self.object_id)
+        self.path = os.path.join(self.cdist_type.path, self.object_id, OBJECT_MARKER)
         self.absolute_path = os.path.join(self.base_path, self.path)
         self.code_local_path = os.path.join(self.path, "code-local")
         self.code_remote_path = os.path.join(self.path, "code-remote")
@@ -138,10 +138,10 @@ class CdistObject(object):
             <CdistObject __foo/bar>.object_from_name('__other/object') -> <CdistObject __other/object>
 
         """
-        type_path = self.type.base_path
+        type_path = self.cdist_type.base_path
         base_path = self.base_path
         type_name, object_id = self.split_name(object_name)
-        return self.__class__(self.type.__class__(type_path, type_name), base_path, object_id=object_id)
+        return self.__class__(self.cdist_type.__class__(type_path, type_name), base_path, object_id=object_id)
 
      def __repr__(self):
         return '<CdistObject %s>' % self.name

From 2492d51f6f5d0741096344e13a3a2c54c782d36a Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 07:56:37 +0100
Subject: [PATCH 46/98] make object_from_name() better readable

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index e7ea7a9f..b6bf0903 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -138,10 +138,15 @@ class CdistObject(object):
             <CdistObject __foo/bar>.object_from_name('__other/object') -> <CdistObject __other/object>
 
         """
-        type_path = self.cdist_type.base_path
+
         base_path = self.base_path
+        type_path = self.cdist_type.base_path
+
         type_name, object_id = self.split_name(object_name)
-        return self.__class__(self.cdist_type.__class__(type_path, type_name), base_path, object_id=object_id)
+
+        cdist_type = self.cdist_type.__class__(type_path, type_name)
+
+        return self.__class__(cdist_type, base_path, object_id=object_id)
 
      def __repr__(self):
         return '<CdistObject %s>' % self.name

From dcd3bcee3258ef6f8bb55047db08151bf2e72770 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 07:57:51 +0100
Subject: [PATCH 47/98] use the great method object_from_name() in emulator

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/emulator.py | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 8174b38f..64773334 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -154,15 +154,7 @@ class Emulator(object):
                 if len(requirement) == 0:
                     continue
 
-                requirement_type_name, requirement_object_id = core.CdistObject.split_name(requirement)
-                # Instantiate type which fails if type does not exist
-                requirement_type = core.CdistType(self.type_base_path,
-                    requirement_type_name)
-
-                # Instantiate object, which fails if object id is broken
-                requirement_object = core.CdistObject(requirement_type,
-                    self.object_base_path, requirement_object_id)
-
+                self.cdist_object.object_from_name(requirement)
                 self.log.debug("Recording requirement: " + requirement)
                 self.cdist_object.requirements.append(requirement)
 

From eadb62e67a9e4136e5321140d8160b01aa4fe931 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 08:44:09 +0100
Subject: [PATCH 48/98] minimal beaufity

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/niconext | 1 -
 lib/cdist/emulator.py | 4 ++--
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index 34c2f7b0..77cbe986 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -1,7 +1,6 @@
 - cleanup object_id handling
     - have a look at singletons
     - double check verification
-    - cleanup emulator to create object
     - adjust tests
 
 --------------------------------------------------------------------------------
diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 64773334..5e95e31c 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -151,9 +151,9 @@ class Emulator(object):
             self.log.debug("reqs = " + requirements)
             for requirement in requirements.split(" "):
                 # Ignore empty fields - probably the only field anyway
-                if len(requirement) == 0:
-                    continue
+                if len(requirement) == 0: continue
 
+                # Raises an error, if object cannot be created
                 self.cdist_object.object_from_name(requirement)
                 self.log.debug("Recording requirement: " + requirement)
                 self.cdist_object.requirements.append(requirement)

From 921b0c0dffb5d09b624cd384b3aa5bf2de90effc Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 08:49:49 +0100
Subject: [PATCH 49/98] do not submit run/exec types containing echo only

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/man/man7/cdist-hacker.text | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/doc/man/man7/cdist-hacker.text b/doc/man/man7/cdist-hacker.text
index 9bdf63d4..646439a3 100644
--- a/doc/man/man7/cdist-hacker.text
+++ b/doc/man/man7/cdist-hacker.text
@@ -61,12 +61,19 @@ including it.
 
 HOW TO SUBMIT A NEW TYPE
 ------------------------
+For detailled information about types, see cdist-type(7).
+
 Submitting a type works as described above, with the additional requirement
 that a corresponding manpage named man.text in asciidoc format with
 the manpage-name "cdist-type__NAME" is included in the type directory
 AND asciidoc is able to compile it (i.e. do NOT have to many "=" in the second
 line).
 
+Warning: Submitting "exec" or "run" types that simply echo their parameter in
+gencode* will not be accepted, because they are of no use. Every type can output
+code and thus such a type introduces redundant functionality that is given by
+core cdist already.
+
 
 SEE ALSO
 --------

From 1e5226e21c9007484982fe076c13087bea714c5f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 08:51:40 +0100
Subject: [PATCH 50/98] fix indention errors due to vim c&p

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index b6bf0903..f425ca60 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -148,7 +148,7 @@ class CdistObject(object):
 
         return self.__class__(cdist_type, base_path, object_id=object_id)
 
-     def __repr__(self):
+    def __repr__(self):
         return '<CdistObject %s>' % self.name
 
     def __eq__(self, other):
@@ -161,7 +161,7 @@ class CdistObject(object):
     def __lt__(self, other):
         return isinstance(other, self.__class__) and self.name < other.name
 
-   def sanitise_object_id(self):
+    def sanitise_object_id(self):
         """
         Remove leading and trailing slash (one only)
         """

From 2bc201614a77f99f554992f5b3260f0047c4c807 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 08:54:09 +0100
Subject: [PATCH 51/98] :%s/cdist_object.type/cdist_object.cdist_type/g

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/explorer.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/lib/cdist/core/explorer.py b/lib/cdist/core/explorer.py
index 43b0339c..bbd2108c 100644
--- a/lib/cdist/core/explorer.py
+++ b/lib/cdist/core/explorer.py
@@ -121,18 +121,18 @@ class Explorer(object):
         in the object.
 
         """
-        self.log.debug("Transfering type explorers for type: %s", cdist_object.type)
-        self.transfer_type_explorers(cdist_object.type)
+        self.log.debug("Transfering type explorers for type: %s", cdist_object.cdist_type)
+        self.transfer_type_explorers(cdist_object.cdist_type)
         self.log.debug("Transfering object parameters for object: %s", cdist_object.name)
         self.transfer_object_parameters(cdist_object)
-        for explorer in self.list_type_explorer_names(cdist_object.type):
+        for explorer in self.list_type_explorer_names(cdist_object.cdist_type):
             output = self.run_type_explorer(explorer, cdist_object)
             self.log.debug("Running type explorer '%s' for object '%s'", explorer, cdist_object.name)
             cdist_object.explorers[explorer] = output
 
     def run_type_explorer(self, explorer, cdist_object):
         """Run the given type explorer for the given object and return it's output."""
-        cdist_type = cdist_object.type
+        cdist_type = cdist_object.cdist_type
         env = self.env.copy()
         env.update({
             '__object': os.path.join(self.remote.object_path, cdist_object.path),

From a8e9b7feedb7485239f877ce1e5d2f2731930d7f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 08:55:42 +0100
Subject: [PATCH 52/98] :%s/cdist_object.type/cdist_object.cdist_type/g

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/manifest.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/core/manifest.py b/lib/cdist/core/manifest.py
index 704a3978..8b784229 100644
--- a/lib/cdist/core/manifest.py
+++ b/lib/cdist/core/manifest.py
@@ -87,7 +87,7 @@ class Manifest(object):
         self.local.run_script(script, env=env)
 
     def run_type_manifest(self, cdist_object):
-        script = os.path.join(self.local.type_path, cdist_object.type.manifest_path)
+        script = os.path.join(self.local.type_path, cdist_object.cdist_type.manifest_path)
         if os.path.isfile(script):
             env = os.environ.copy()
             env.update(self.env)
@@ -96,7 +96,7 @@ class Manifest(object):
                 '__object_id': cdist_object.object_id,
                 '__object_name': cdist_object.name,
                 '__self': cdist_object.name,
-                '__type': cdist_object.type.absolute_path,
+                '__type': cdist_object.cdist_type.absolute_path,
                 '__cdist_manifest': script,
             })
             self.local.run_script(script, env=env)

From 8f75a9133fae3a75f459aa5314934bb58db042e5 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 10:38:36 +0100
Subject: [PATCH 53/98] do not fail validation on empty object_id

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index f425ca60..3c2de01b 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -166,13 +166,15 @@ class CdistObject(object):
         Remove leading and trailing slash (one only)
         """
 
-        # Remove leading slash
-        if self.object_id[0] == '/':
-            self.object_id = self.object_id[1:]
+        # Allow empty object id for singletons
+        if self.object_id:
+            # Remove leading slash
+            if self.object_id[0] == '/':
+                self.object_id = self.object_id[1:]
 
-        # Remove trailing slash
-        if self.object_id[-1] == '/':
-            self.object_id = self.object_id[:-1]
+            # Remove trailing slash
+            if self.object_id[-1] == '/':
+                self.object_id = self.object_id[:-1]
 
     # FIXME: still needed?
     @property

From 0851af7d52e98f30ad5454a000c6a7291b62539c Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 10:39:04 +0100
Subject: [PATCH 54/98] allow object_id to start and end with one /, fail with
 any //

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/test/object/__init__.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/test/object/__init__.py b/lib/cdist/test/object/__init__.py
index 0f8c0189..72530910 100644
--- a/lib/cdist/test/object/__init__.py
+++ b/lib/cdist/test/object/__init__.py
@@ -54,9 +54,9 @@ class ObjectClassTestCase(test.CdistTestCase):
 
 
 class ObjectIdTestCase(test.CdistTestCase):
-    def test_object_id_starts_with_slash(self):
+    def test_object_id_contains_double_slash(self):
         cdist_type = core.CdistType(type_base_path, '__third')
-        illegal_object_id = '/object_id/may/not/start/with/slash'
+        illegal_object_id = '/object_id//may/not/contain/double/slash'
         with self.assertRaises(core.IllegalObjectIdError):
             core.CdistObject(cdist_type, object_base_path, illegal_object_id)
 

From f12a83f3dddbe6481581b594ba8ee119f00181c7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 10:41:12 +0100
Subject: [PATCH 55/98] -migration to CdistType error

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/niconext             | 3 +++
 lib/cdist/core/code.py            | 4 ++--
 lib/cdist/test/object/__init__.py | 2 +-
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index 77cbe986..dd20026c 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -3,6 +3,9 @@
     - double check verification
     - adjust tests
 
+- remove useless
+    ERROR: monitoring02: Code that raised the error:
+
 --------------------------------------------------------------------------------
 
 - __user
diff --git a/lib/cdist/core/code.py b/lib/cdist/core/code.py
index 51912559..7e69f21c 100644
--- a/lib/cdist/core/code.py
+++ b/lib/cdist/core/code.py
@@ -96,13 +96,13 @@ class Code(object):
             self.env.update({'__debug': "yes" })
 
     def _run_gencode(self, cdist_object, which):
-        cdist_type = cdist_object.type
+        cdist_type = cdist_object.cdist_type
         script = os.path.join(self.local.type_path, getattr(cdist_type, 'gencode_%s_path' % which))
         if os.path.isfile(script):
             env = os.environ.copy()
             env.update(self.env)
             env.update({
-                '__type': cdist_object.type.absolute_path,
+                '__type': cdist_object.cdist_type.absolute_path,
                 '__object': cdist_object.absolute_path,
                 '__object_id': cdist_object.object_id,
                 '__object_name': cdist_object.name,
diff --git a/lib/cdist/test/object/__init__.py b/lib/cdist/test/object/__init__.py
index 72530910..3a91f709 100644
--- a/lib/cdist/test/object/__init__.py
+++ b/lib/cdist/test/object/__init__.py
@@ -198,5 +198,5 @@ class ObjectTestCase(test.CdistTestCase):
         other_name = '__first/man'
         other_object = self.cdist_object.object_from_name(other_name)
         self.assertTrue(isinstance(other_object, core.CdistObject))
-        self.assertEqual(other_object.type.name, '__first')
+        self.assertEqual(other_object.cdist_type.name, '__first')
         self.assertEqual(other_object.object_id, 'man')

From 2fce038423813a0d07c294ac1d08e5731ec77367 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 10:43:42 +0100
Subject: [PATCH 56/98] correct catching exception to IllegalObjectIdError

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/test/emulator/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cdist/test/emulator/__init__.py b/lib/cdist/test/emulator/__init__.py
index c0037b68..f1ea5832 100644
--- a/lib/cdist/test/emulator/__init__.py
+++ b/lib/cdist/test/emulator/__init__.py
@@ -79,7 +79,7 @@ class EmulatorTestCase(test.CdistTestCase):
         os.environ.update(self.env)
         os.environ['require'] = '__file'
         emu = emulator.Emulator(argv)
-        self.assertRaises(emulator.IllegalRequirementError, emu.run)
+        self.assertRaises(core.IllegalObjectIdError, emu.run)
 
     def test_singleton_object_requirement(self):
         argv = ['__file', '/tmp/foobar']

From 2d6107002357af985d7695082e98caea99ae4a31 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 10:47:40 +0100
Subject: [PATCH 57/98] remove old IllegalRequirementError exception

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/emulator.py | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 5e95e31c..8daa61fb 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -26,15 +26,6 @@ import os
 import cdist
 from cdist import core
 
-
-class IllegalRequirementError(cdist.Error):
-    def __init__(self, requirement, message=None):
-        self.requirement = requirement
-        self.message = message or 'Illegal requirement'
-
-    def __str__(self):
-        return '%s: %s' % (self.message, self.requirement)
-
 class Emulator(object):
     def __init__(self, argv):
         self.argv           = argv
@@ -155,6 +146,7 @@ class Emulator(object):
 
                 # Raises an error, if object cannot be created
                 self.cdist_object.object_from_name(requirement)
+
                 self.log.debug("Recording requirement: " + requirement)
                 self.cdist_object.requirements.append(requirement)
 

From 95cbdeba277b04535f60068e725b07b43138c2c5 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 11:30:11 +0100
Subject: [PATCH 58/98] document /, // behaviour of object id

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/changelog                   |   3 +
 doc/dev/todo/niconext           |   2 -
 doc/man/cdist-reference.text.sh | 138 ++++++++++++++++----------------
 3 files changed, 74 insertions(+), 69 deletions(-)

diff --git a/doc/changelog b/doc/changelog
index dace28dd..899b4b21 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -9,7 +9,10 @@ Changelog
 	* Bugfix __user: Correct shadow field in explorer (Matt Coddington)
 	* Bugfix __link: Properly handle existing links (Steven Armstrong)
 	* Bugfix __key_value: More robust implementation (Steven Armstrong)
+	* Bugfix __user: Fix for changing a user's group by name (Matt Coddington)
 	* New Type: __package_pip
+	* Bugfix/Cleanup: Correctly allow Object ID to start and end with /, but
+		not contain //.
 
 2.0.6: 2012-01-28
 	* Bugfix __apt_ppa:
diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index dd20026c..6dafda9a 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -1,7 +1,5 @@
 - cleanup object_id handling
     - have a look at singletons
-    - double check verification
-    - adjust tests
 
 - remove useless
     ERROR: monitoring02: Code that raised the error:
diff --git a/doc/man/cdist-reference.text.sh b/doc/man/cdist-reference.text.sh
index 898771c7..bf8d250e 100755
--- a/doc/man/cdist-reference.text.sh
+++ b/doc/man/cdist-reference.text.sh
@@ -49,10 +49,10 @@ The following global explorers are available:
 
 eof
 (
-   cd ../../conf/explorer
-   for explorer in *; do
-      echo "- $explorer"
-   done
+    cd ../../conf/explorer
+    for explorer in *; do
+       echo "- $explorer"
+    done
 )
 
 cat << eof 
@@ -62,77 +62,77 @@ PATHS
 If not specified otherwise, all paths are relative to the checkout directory.
 
 conf/::
-   Contains the (static) configuration like manifests, types and explorers.  
+    Contains the (static) configuration like manifests, types and explorers.  
 
 conf/manifest/init::
-   This is the central entry point used by cdist-manifest-init(1).
-   It is an executable (+x bit set) shell script that can use
-   values from the explorers to decide which configuration to create
-   for the specified target host.
-   It should be primary used to define mapping from configurations to hosts.
+    This is the central entry point used by cdist-manifest-init(1).
+    It is an executable (+x bit set) shell script that can use
+    values from the explorers to decide which configuration to create
+    for the specified target host.
+    It should be primary used to define mapping from configurations to hosts.
 
 conf/manifest/*::
-   All other files in this directory are not directly used by cdist, but you
-   can seperate configuration mappings, if you have a lot of code in the
-   manifest/init file. This may also be helpful to have different admins
-   maintain different groups of hosts.
+    All other files in this directory are not directly used by cdist, but you
+    can seperate configuration mappings, if you have a lot of code in the
+    manifest/init file. This may also be helpful to have different admins
+    maintain different groups of hosts.
 
 conf/explorer/<name>::
-   Contains explorers to be run on the target hosts, see cdist-explorer(7).
+    Contains explorers to be run on the target hosts, see cdist-explorer(7).
 
 conf/type/::
-   Contains all available types, which are used to provide
-   some kind of functionality. See cdist-type(7).
+    Contains all available types, which are used to provide
+    some kind of functionality. See cdist-type(7).
 
 conf/type/<name>/::
-   Home of the type <name>.
+    Home of the type <name>.
 
-   This directory is referenced by the variable __type (see below).
+    This directory is referenced by the variable __type (see below).
 
 conf/type/<name>/man.text::
-   Manpage in Asciidoc format (required for inclusion into upstream)
+    Manpage in Asciidoc format (required for inclusion into upstream)
 
 conf/type/<name>/manifest::
-   Used to generate additional objects from a type.
+    Used to generate additional objects from a type.
 
 conf/type/<name>/gencode-local::
-   Used to generate code to be executed on the server.
+    Used to generate code to be executed on the server.
 
 conf/type/<name>/gencode-remote::
-   Used to generate code to be executed on the client.
+    Used to generate code to be executed on the client.
 
 conf/type/<name>/parameters/required::
-   Parameters required by type, \n seperated list.
+    Parameters required by type, \n seperated list.
 
 conf/type/<name>/parameters/optional::
-   Parameters optionally accepted by type, \n seperated list.
+    Parameters optionally accepted by type, \n seperated list.
 
 conf/type/<name>/explorer::
-   Location of the type specific explorers.
-   This directory is referenced by the variable __type_explorer (see below).
-   See cdist-explorer(7).
+    Location of the type specific explorers.
+    This directory is referenced by the variable __type_explorer (see below).
+    See cdist-explorer(7).
 
 out/::
-   This directory contains output of cdist and is usually located
-   in a temporary directory and thus will be removed after the run.
-   This directory is referenced by the variable __global (see below).
+    This directory contains output of cdist and is usually located
+    in a temporary directory and thus will be removed after the run.
+    This directory is referenced by the variable __global (see below).
 
 out/explorer::
-   Output of general explorers.
+    Output of general explorers.
 
 out/object::
-   Objects created for the host.
+    Objects created for the host.
 
 out/object/<object>::
-   Contains all object specific information.
-   This directory is referenced by the variable __object (see below).
+    Contains all object specific information.
+    This directory is referenced by the variable __object (see below).
 
 out/object/<object>/explorers::
-   Output of type specific explorers, per object.
+    Output of type specific explorers, per object.
 
 tmp_dir::
-   A tempdir and a tempfile is used by cdist internally,
-   which will be removed when the scripts end automatically.
+    A tempdir and a tempfile is used by cdist internally,
+    which will be removed when the scripts end automatically.
 
 TYPES
 -----
@@ -141,13 +141,13 @@ The following types are available:
 eof
 
 for type in man7/cdist-type__*.text; do
-   no_dir="${type#man7/}";
-   no_type="${no_dir#cdist-type}";
-   name="${no_type%.text}";
-   name_no_underline="$(echo $name | sed 's/^__/\\__/g')"
-   man="${no_dir%.text}(7)"
+    no_dir="${type#man7/}";
+    no_type="${no_dir#cdist-type}";
+    name="${no_type%.text}";
+    name_no_underline="$(echo $name | sed 's/^__/\\__/g')"
+    man="${no_dir%.text}(7)"
 
-   echo "- $name_no_underline" "($man)"
+    echo "- $name_no_underline" "($man)"
 done
 
 cat << eof
@@ -159,43 +159,47 @@ For object to object communication and tests, the following paths are
 usable within a object directory:
 
 changed::
-   This empty file exists in an object directory, if the object has
-   code to be excuted (either remote or local)
+    This empty file exists in an object directory, if the object has
+    code to be excuted (either remote or local)
 
 
 ENVIRONMENT VARIABLES
 ---------------------
 __explorer::
-   Directory that contains all global explorers.
-   Available for: explorer
+    Directory that contains all global explorers.
+    Available for: explorer
 __manifest::
-   Directory that contains the initial manifest.
-   Available for: initial manifest
+    Directory that contains the initial manifest.
+    Available for: initial manifest
 __global::
-   Directory that contains generic output like explorer.
-   Available for: initial manifest, type manifest, type gencode
+    Directory that contains generic output like explorer.
+    Available for: initial manifest, type manifest, type gencode
 __object::
-   Directory that contains the current object.
-   Available for: type manifest, type explorer, type gencode
+    Directory that contains the current object.
+    Available for: type manifest, type explorer, type gencode
 __object_id::
-   The type unique object id.
-   Available for: type manifest, type explorer, type gencode
-   Note: The leading "/" will always be stripped.
+    The type unique object id.
+    Available for: type manifest, type explorer, type gencode
+
+    Note: The leading and the trailing "/" will always be stripped (caused by
+    the filesystem database and ensured by the core).
+
+    Note: Double slashes ("//") will not be fixed and result in an error.
 __self::
-   DEPRECATED: Same as __object_name, do not use anymore, use __object_name instead.
-   Will be removed in cdist 3.x.
+    DEPRECATED: Same as __object_name, do not use anymore, use __object_name instead.
+    Will be removed in cdist 3.x.
 __object_name::
-   The full qualified name of the current object.
-   Available for: type manifest, type explorer, type gencode
+    The full qualified name of the current object.
+    Available for: type manifest, type explorer, type gencode
 __target_host::
-   The host we are deploying to.
-   Available for: initial manifest, type manifest, type gencode
+    The host we are deploying to.
+    Available for: initial manifest, type manifest, type gencode
 __type::
-   Path to the current type.
-   Available for: type manifest, type gencode
+    Path to the current type.
+    Available for: type manifest, type gencode
 __type_explorer::
-   Directory that contains the type explorers.
-   Available for: type explorer
+    Directory that contains the type explorers.
+    Available for: type explorer
 
 
 SEE ALSO

From e3ab8ef77ba80301e08ac65d16bc668e22ed2e7c Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:25:11 +0100
Subject: [PATCH 59/98] version increment

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cdist/__init__.py b/lib/cdist/__init__.py
index 664b6456..800bdaa2 100644
--- a/lib/cdist/__init__.py
+++ b/lib/cdist/__init__.py
@@ -19,7 +19,7 @@
 #
 #
 
-VERSION     = "2.0.6"
+VERSION     = "2.0.7"
 
 BANNER = """
              ..          .       .x+=:.        s

From c8ec4c200aa9b369f9fd3926b18f641598a3cd59 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:28:30 +0100
Subject: [PATCH 60/98] repair manpage for __package_pip

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__package_pip/man.text | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/conf/type/__package_pip/man.text b/conf/type/__package_pip/man.text
index 1822ffca..5ce45c50 100644
--- a/conf/type/__package_pip/man.text
+++ b/conf/type/__package_pip/man.text
@@ -1,5 +1,5 @@
 cdist-type__package_pip(7)
-=============================
+==========================
 Nico Schottelius <nico-cdist--@--schottelius.org>
 
 

From f9ab756ee5c6528de17e0c54bc1ddab6b7b03eec Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:29:04 +0100
Subject: [PATCH 61/98] cleanup todo

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/niconext | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index 6dafda9a..f81c7570 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -1,16 +1,16 @@
+2.0.8 features / cleanups:
+
 - cleanup object_id handling
     - have a look at singletons
 
 - remove useless
     ERROR: monitoring02: Code that raised the error:
 
---------------------------------------------------------------------------------
-
-- __user
-   add option to include --create-home
 - ensure that all types, which support --state support
     present and absent (consistent look and feel)
 
+--------------------------------------------------------------------------------
+
 - update/create docs
     - cdist-cache::
         How to get use information about the hosts we have been working on [advanced]

From 84b6df2e815d8c69d5c004883b62995c354cd24e Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:29:44 +0100
Subject: [PATCH 62/98] ++todo for anyone

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/TAKEME | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/doc/dev/todo/TAKEME b/doc/dev/todo/TAKEME
index 95bda7fb..b40936f6 100644
--- a/doc/dev/todo/TAKEME
+++ b/doc/dev/todo/TAKEME
@@ -35,3 +35,5 @@ USER INTERFACE
 TYPES
 ------
 - Add testing framework (proposed by Evax Software)
+- __user
+   add option to include --create-home

From 632146114ca07254b0119510758316ffc68ffc37 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:30:27 +0100
Subject: [PATCH 63/98] update copyright

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index 3c2de01b..9937c823 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 #
 # 2011 Steven Armstrong (steven-cdist at armstrong.cc)
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
 #
 # This file is part of cdist.
 #

From 06cf5ec3c94435e1cc82cd349302cb09d2200135 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:37:10 +0100
Subject: [PATCH 64/98] check release before releasing...

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build b/build
index ea4ca83c..7da51ded 100755
--- a/build
+++ b/build
@@ -85,7 +85,7 @@ case "$1" in
    ;;
 
    release)
-      "$0" clean && "$0" man && "$0" web
+        ./doc/dev/releasechecklist && "$0" clean && "$0" man && "$0" web
    ;;
 
    speeches)

From f8de3afb5f3712eda304b5592682a51a5c1c1645 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:37:30 +0100
Subject: [PATCH 65/98] +releasedate

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/changelog | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/changelog b/doc/changelog
index 899b4b21..00823886 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -4,7 +4,7 @@ Changelog
 	* Changes are always commented with their author in (braces)
 	* Exception: No braces means author == Nico Schottelius
 
-2.0.7:
+2.0.7: 2012-02-13
 	* Bugfix __file: Use chmod after chown/chgrp (Matt Coddington)
 	* Bugfix __user: Correct shadow field in explorer (Matt Coddington)
 	* Bugfix __link: Properly handle existing links (Steven Armstrong)

From 762b8e0a3ad9d414281f8b7443254c98a878767e Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:48:22 +0100
Subject: [PATCH 66/98] also check date on release

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/releasechecklist | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/doc/dev/releasechecklist b/doc/dev/releasechecklist
index 19ab7b18..3473ae0f 100755
--- a/doc/dev/releasechecklist
+++ b/doc/dev/releasechecklist
@@ -15,11 +15,21 @@ changelog_version=$(grep '^[[:digit:]]' doc/changelog | head -n1 | sed 's/:.*//'
 #git_version=$(git describe)
 lib_version=$(grep ^VERSION lib/cdist/__init__.py | sed -e 's/.*= //' -e 's/"//g')
 
+# get date
+date_today="$(date +%Y-%m-%d)"
+date_changelogn=$(grep '^[[:digit:]]' doc/changelog | head -n1 | sed 's/.*: //')
+
 echo "Ensure you fixed/prepared version files: $files"
 echo "changelog: $changelog_version"
 #echo "git: $git_version"
 echo "lib: $lib_version"
 
+if [ "$date_today" != "$date_changelog" ]; then
+    echo "Messed up date, not releasing:"
+    echo "Changelog: $date_changelog"
+    exit 1
+fi
+
 if [ "$lib_version" != "$changelog_version" ]; then
     echo "Messed up versions, not releasing"
     exit 1

From 992584582853f41b1491f80a31384fc19555f55b Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:49:36 +0100
Subject: [PATCH 67/98] only need release script for release

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build b/build
index 7da51ded..6b415391 100755
--- a/build
+++ b/build
@@ -85,7 +85,7 @@ case "$1" in
    ;;
 
    release)
-        ./doc/dev/releasechecklist && "$0" clean && "$0" man && "$0" web
+        ./doc/dev/releasechecklist
    ;;
 
    speeches)

From edd93aa1f899ca05dd9bf7487bbbf3b67336115a Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 14:55:41 +0100
Subject: [PATCH 68/98] -typo

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/releasechecklist | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/dev/releasechecklist b/doc/dev/releasechecklist
index 3473ae0f..eba81dc0 100755
--- a/doc/dev/releasechecklist
+++ b/doc/dev/releasechecklist
@@ -17,7 +17,7 @@ lib_version=$(grep ^VERSION lib/cdist/__init__.py | sed -e 's/.*= //' -e 's/"//g
 
 # get date
 date_today="$(date +%Y-%m-%d)"
-date_changelogn=$(grep '^[[:digit:]]' doc/changelog | head -n1 | sed 's/.*: //')
+date_changelog=$(grep '^[[:digit:]]' doc/changelog | head -n1 | sed 's/.*: //')
 
 echo "Ensure you fixed/prepared version files: $files"
 echo "changelog: $changelog_version"

From f8868349e6f1fa7694a5aef3220990ec6b8039f6 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 15:01:45 +0100
Subject: [PATCH 69/98] cdist_object.type => cdist_object.cdist_type

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/config_install.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cdist/config_install.py b/lib/cdist/config_install.py
index f27fff77..7cce240e 100644
--- a/lib/cdist/config_install.py
+++ b/lib/cdist/config_install.py
@@ -112,7 +112,7 @@ class ConfigInstall(object):
             # TODO: remove once we are sure that this really never happens.
             raise cdist.Error("Attempting to run an already finished object: %s", cdist_object)
 
-        cdist_type = cdist_object.type
+        cdist_type = cdist_object.cdist_type
 
         # Generate
         self.log.info("Generating and executing code for " + cdist_object.name)

From ba0130594cb51d826f311116dc73caacf2ca518e Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 15:20:33 +0100
Subject: [PATCH 70/98] remove latest before linking to prevent symlink below
 latest/

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 build | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build b/build
index 6b415391..b994ce00 100755
--- a/build
+++ b/build
@@ -123,7 +123,7 @@ case "$1" in
       # Fix ikiwiki, which does not like symlinks for pseudo security
       ssh tee.schottelius.org \
         "cd /home/services/www/nico/www.nico.schottelius.org/www/software/cdist/man &&
-            ln -sf "$version" latest"
+            rm -f latest && ln -sf "$version" latest"
    ;;
 
    p|pu|pub)

From 08612764362c629b9b144db64277abbe7f200b9c Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 16:14:48 +0100
Subject: [PATCH 71/98] remove obsolete MissingEnvironmentVariableError()

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/__init__.py | 10 ----------
 lib/cdist/emulator.py |  2 +-
 2 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/lib/cdist/__init__.py b/lib/cdist/__init__.py
index 800bdaa2..973b61f8 100644
--- a/lib/cdist/__init__.py
+++ b/lib/cdist/__init__.py
@@ -44,16 +44,6 @@ class Error(Exception):
     """Base exception class for this project"""
     pass
 
-
-class MissingEnvironmentVariableError(Error):
-    """Raised when a required environment variable is not set."""
-
-    def __init__(self, name):
-        self.name = name
-
-    def __str__(self):
-        return 'Missing required environment variable: ' + str(self.name)
-
 def file_to_list(filename):
     """Return list from \n seperated file"""
     if os.path.isfile(filename):
diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 8daa61fb..687aee93 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 #
-# 2011 Nico Schottelius (nico-cdist at schottelius.org)
+# 2011-2012 Nico Schottelius (nico-cdist at schottelius.org)
 #
 # This file is part of cdist.
 #

From d51a177a9545f9d534c24c25239144a6f8bd4b3d Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 16:22:14 +0100
Subject: [PATCH 72/98] invent a generic CdistObjectError and point to
 definition source (easier debugging)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/__init__.py | 12 ++++++++++++
 lib/cdist/resolver.py |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/lib/cdist/__init__.py b/lib/cdist/__init__.py
index 973b61f8..4742a937 100644
--- a/lib/cdist/__init__.py
+++ b/lib/cdist/__init__.py
@@ -44,6 +44,18 @@ class Error(Exception):
     """Base exception class for this project"""
     pass
 
+class CdistObjectError(Error):
+    """Something went wrong with an object"""
+    
+    def __init__(self, cdist_object, message):
+        self.name = cdist_object.name
+        self.source = " ".join(cdist_object.source)
+        self.message = message
+
+
+    def __str__(self):
+        return '%s: %s (defined at %s)' % (self.name, self.message, self.source)
+
 def file_to_list(filename):
     """Return list from \n seperated file"""
     if os.path.isfile(filename):
diff --git a/lib/cdist/resolver.py b/lib/cdist/resolver.py
index 24a5e496..368c9eb8 100644
--- a/lib/cdist/resolver.py
+++ b/lib/cdist/resolver.py
@@ -125,7 +125,7 @@ class DependencyResolver(object):
             resolved.append(cdist_object)
             unresolved.remove(cdist_object)
         except RequirementNotFoundError as e:
-            raise cdist.Error(cdist_object.name + " requires non-existing " + e.requirement)
+            raise cdist.CdistObjectError(cdist_object, "requires non-existing " + e.requirement)
 
     def __iter__(self):
         """Iterate over all unique objects while resolving dependencies.

From 8f1735fab2b69e4b5c21cacb97230626e08d0cde Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 16:22:46 +0100
Subject: [PATCH 73/98] ++changes(2.0.8)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/changelog | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/doc/changelog b/doc/changelog
index 00823886..c241624a 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -4,6 +4,9 @@ Changelog
 	* Changes are always commented with their author in (braces)
 	* Exception: No braces means author == Nico Schottelius
 
+2.0.8:
+	* Cleanup: Better hint to source of error
+
 2.0.7: 2012-02-13
 	* Bugfix __file: Use chmod after chown/chgrp (Matt Coddington)
 	* Bugfix __user: Correct shadow field in explorer (Matt Coddington)

From c9ae06db6428855a3d9d849efd1019346b203c06 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Mon, 13 Feb 2012 16:27:41 +0100
Subject: [PATCH 74/98] do not setup __debug - let the user do if required - do
 not interfere type with core

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/changelog              | 2 ++
 lib/cdist/core/code.py     | 3 ---
 lib/cdist/core/explorer.py | 2 --
 3 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/doc/changelog b/doc/changelog
index c241624a..2d2d7a48 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -6,6 +6,8 @@ Changelog
 
 2.0.8:
 	* Cleanup: Better hint to source of error
+	* Cleanup: Remove support for __debug variable in manifests (Type != Core
+		debugging)
 
 2.0.7: 2012-02-13
 	* Bugfix __file: Use chmod after chown/chgrp (Matt Coddington)
diff --git a/lib/cdist/core/code.py b/lib/cdist/core/code.py
index 7e69f21c..2ffef9cf 100644
--- a/lib/cdist/core/code.py
+++ b/lib/cdist/core/code.py
@@ -92,9 +92,6 @@ class Code(object):
             '__global': self.local.out_path,
         }
 
-        if log.getEffectiveLevel() == logging.DEBUG:
-            self.env.update({'__debug': "yes" })
-
     def _run_gencode(self, cdist_object, which):
         cdist_type = cdist_object.cdist_type
         script = os.path.join(self.local.type_path, getattr(cdist_type, 'gencode_%s_path' % which))
diff --git a/lib/cdist/core/explorer.py b/lib/cdist/core/explorer.py
index bbd2108c..d49b7ac4 100644
--- a/lib/cdist/core/explorer.py
+++ b/lib/cdist/core/explorer.py
@@ -73,8 +73,6 @@ class Explorer(object):
             '__target_host': self.target_host,
             '__explorer': self.remote.global_explorer_path,
         }
-        if self.log.getEffectiveLevel() == logging.DEBUG:
-            self.env.update({'__debug': "yes" })
         self._type_explorers_transferred = []
 
     ### global

From 861b13ffe48ae5ed5867ec9efd9f0fa92145fc71 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 14 Feb 2012 11:12:17 +0100
Subject: [PATCH 75/98] record sanitised object, not the user supplied one, as
 requirement

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/emulator.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 687aee93..0979182a 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -145,10 +145,14 @@ class Emulator(object):
                 if len(requirement) == 0: continue
 
                 # Raises an error, if object cannot be created
-                self.cdist_object.object_from_name(requirement)
+                cdist_object = self.cdist_object.object_from_name(requirement)
 
                 self.log.debug("Recording requirement: " + requirement)
-                self.cdist_object.requirements.append(requirement)
+
+                # Save the sanitised version, not the user supplied one
+                # (__file//bar => __file/bar)
+                # This ensures pattern matching is done against sanitised list
+                self.cdist_object.requirements.append(cdist_object.name)
 
     def record_auto_requirements(self):
         """An object shall automatically depend on all objects that it defined in it's type manifest.

From df54ab328435781f0e098c60894f95382c8e3cc4 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 14 Feb 2012 11:15:02 +0100
Subject: [PATCH 76/98] mark same algorithmus for deps in logs

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/logs/2012-02-13.dependencies | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 doc/dev/logs/2012-02-13.dependencies

diff --git a/doc/dev/logs/2012-02-13.dependencies b/doc/dev/logs/2012-02-13.dependencies
new file mode 100644
index 00000000..3b0f3f21
--- /dev/null
+++ b/doc/dev/logs/2012-02-13.dependencies
@@ -0,0 +1,23 @@
+possible dependencies:
+
+    - unix pattern __foo/*
+    - object: __foo//bar, __foo/bar
+    - singleton with object_id: __foo/singleton
+    - singleton without object_id: __foo/
+
+solving dependencies:
+
+    solve_dep(object, run_list):
+        - list = [me]
+        - if status == IN_DEPENDENCY:
+            fail: circular dependency
+        - status = IN_DEPENDENCY
+        - create_list_of_deps(object)
+            - try pattern expansion
+        - for each dependency:
+            if object does not exist:
+                fail
+            else:
+                list.append(solve_dep(object, run_list)):
+        - status == IN_LIST
+        - return [me, dependencies [, dependencies of dependencies]]

From 0082b7f07cd821b80f24fb8d23524706bba531d9 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 14 Feb 2012 12:41:13 +0100
Subject: [PATCH 77/98] allow objects to start with /, but not to contain //;
 sanitise after validation

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/core/cdist_object.py | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/lib/cdist/core/cdist_object.py b/lib/cdist/core/cdist_object.py
index 9937c823..e12bcfbd 100644
--- a/lib/cdist/core/cdist_object.py
+++ b/lib/cdist/core/cdist_object.py
@@ -102,8 +102,6 @@ class CdistObject(object):
         """Validate the given object_id and raise IllegalObjectIdError if it's not valid.
         """
         if self.object_id:
-            if self.object_id.startswith('/'):
-                raise IllegalObjectIdError(self.object_id, 'object_id may not start with /')
             if OBJECT_MARKER in self.object_id.split(os.sep):
                 raise IllegalObjectIdError(self.object_id, 'object_id may not contain \'%s\'' % OBJECT_MARKER)
             if '//' in self.object_id:
@@ -119,8 +117,8 @@ class CdistObject(object):
         self.base_path = base_path
         self.object_id = object_id
 
-        self.sanitise_object_id()
         self.validate_object_id()
+        self.sanitise_object_id()
 
         self.name = self.join_name(self.cdist_type.name, self.object_id)
         self.path = os.path.join(self.cdist_type.path, self.object_id, OBJECT_MARKER)

From 365c629db9578790725e8dd981894f62abc1b97e Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 14 Feb 2012 13:55:50 +0100
Subject: [PATCH 78/98] update variable availbility list in reference

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/man/cdist-reference.text.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/man/cdist-reference.text.sh b/doc/man/cdist-reference.text.sh
index bf8d250e..81e58ab2 100755
--- a/doc/man/cdist-reference.text.sh
+++ b/doc/man/cdist-reference.text.sh
@@ -167,7 +167,7 @@ ENVIRONMENT VARIABLES
 ---------------------
 __explorer::
     Directory that contains all global explorers.
-    Available for: explorer
+    Available for: explorer, type explorer
 __manifest::
     Directory that contains the initial manifest.
     Available for: initial manifest
@@ -193,7 +193,7 @@ __object_name::
     Available for: type manifest, type explorer, type gencode
 __target_host::
     The host we are deploying to.
-    Available for: initial manifest, type manifest, type gencode
+    Available for: explorer, initial manifest, type explorer, type manifest, type gencode
 __type::
     Path to the current type.
     Available for: type manifest, type gencode

From 2b0c2737151b52d38aa449b9cefc42fa19957cbb Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 14 Feb 2012 18:04:00 +0100
Subject: [PATCH 79/98] state_should is being populated in manifest, if not
 given

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index 09c4912d..6618b9b0 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -19,12 +19,7 @@
 #
 #
 
-if [ -f "$__object/parameter/state" ]; then
-    state_should="$(cat "$__object/parameter/state")"
-else
-    state_should="present"
-fi
-
+state_should="$(cat "$__object/parameter/state")"
 state_is=$(cat "$__object/explorer/state")
 
 # Nothing todo, go away

From 2f16b08bb0247e7ba5454f43b2dea6bf33691636 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 14 Feb 2012 20:31:02 +0100
Subject: [PATCH 80/98] also copy over the .css for manpages

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 build | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/build b/build
index b994ce00..2d98e862 100755
--- a/build
+++ b/build
@@ -113,8 +113,8 @@ case "$1" in
       # cp ${SPEECHESDIR}/*.pdf ${WEBDIR}/${WEBBASE}/speeches
       # git describe > ${WEBDIR}/${WEBBASE}/man/VERSION
 
-      cp ${MAN1DSTDIR}/*.html ${WEBMAN}/man1 
-      cp ${MAN7DSTDIR}/*.html ${WEBMAN}/man7
+      cp ${MAN1DSTDIR}/*.html ${MAN1DSTDIR}/*.css ${WEBMAN}/man1 
+      cp ${MAN7DSTDIR}/*.html ${MAN7DSTDIR}/*.css ${WEBMAN}/man7
       
       cd ${WEBDIR} && git add ${WEBBASE}
       cd ${WEBDIR} && git commit -m "cdist update" ${WEBBASE} ${WEBPAGE}

From 5d47eb849f5f8f78a8a63932316e14da894323f9 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Tue, 14 Feb 2012 20:31:16 +0100
Subject: [PATCH 81/98] some stuff to be fixed

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index 6618b9b0..3db7293f 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -35,13 +35,13 @@ case "$state_should" in
                 echo sed -i /etc/rc.conf \'s/^\\(DAEMONS=.*\\))/\\1 $name)/\'
             ;;
             debian|ubuntu)
-                # This does not work as expected:
+                # FIXME: This does not work as expected:
                 # insserv: warning: current start runlevel(s) (3 4 5) of script `postfix' overwrites defaults (2 3 4 5).
                 #echo update-rc.d \"$name\" defaults
                 echo update-rc.d \"$name\" defaults
             ;;
 
-# Disabled until the explorer is checked
+#           FIXME: Disabled until the explorer is checked
 #            gentoo)
 #                echo rc-update add \"$name\" default
 #            ;;
@@ -60,13 +60,14 @@ case "$state_should" in
     absent)
         case "$os" in
             archlinux)
-                echo sed -i /etc/rc.conf -e \"s/ $name / /g\" -e \"s/($name/(/\" -e \"s/ $name)/)/\"
+                # Replace a) at the beginning b) in the middle c) end d) only
+                echo "sed -i /etc/rc.conf -e 's/^\(DAEMONS=(\)$name /\1/' -e 's/^\(DAEMONS=(.* \)$name \(.*\)/\1\2/' -e 's/^\(DAEMONS=(.*\) $name)/\1)/' -e 's/^\(DAEMONS=(\)$name)/\1)/'"
             ;;
             debian|ubuntu)
                 echo update-rc.d -f \"$name\" remove
             ;;
 
-# Disabled until the explorer is checked
+# FIXME: Disabled until the explorer is checked
 #            gentoo)
 #                echo rc-update del \"$name\"
 #            ;;

From d427af2ee33875f271c413ecde5421640448ae72 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 08:50:03 +0100
Subject: [PATCH 82/98] add hint on incomplete type

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/man.text | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/conf/type/__start_on_boot/man.text b/conf/type/__start_on_boot/man.text
index e9691401..0e75c9ab 100644
--- a/conf/type/__start_on_boot/man.text
+++ b/conf/type/__start_on_boot/man.text
@@ -13,6 +13,9 @@ DESCRIPTION
 This cdist type allows you to enable or disable stuff to be started
 at boot of your operating system.
 
+Warning: This type has not been tested intensively and is not fully
+supported (i.e. gentoo and *bsd are not implemented).
+
 
 REQUIRED PARAMETERS
 -------------------

From 824ec459ea3ce1dbc2c2751071a42eb235eae66e Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 08:50:26 +0100
Subject: [PATCH 83/98] cleanups in gencode

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index 3db7293f..f1788d4b 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -32,13 +32,10 @@ case "$state_should" in
     present)
         case "$os" in
             archlinux)
-                echo sed -i /etc/rc.conf \'s/^\\(DAEMONS=.*\\))/\\1 $name)/\'
+                echo "sed -i /etc/rc.conf \'s/^\\(DAEMONS=.*\\))/\\1 $name)/\'"
             ;;
             debian|ubuntu)
-                # FIXME: This does not work as expected:
-                # insserv: warning: current start runlevel(s) (3 4 5) of script `postfix' overwrites defaults (2 3 4 5).
-                #echo update-rc.d \"$name\" defaults
-                echo update-rc.d \"$name\" defaults
+                echo "update-rc.d \"$name\" defaults >/dev/null"
             ;;
 
 #           FIXME: Disabled until the explorer is checked
@@ -61,7 +58,7 @@ case "$state_should" in
         case "$os" in
             archlinux)
                 # Replace a) at the beginning b) in the middle c) end d) only
-                echo "sed -i /etc/rc.conf -e 's/^\(DAEMONS=(\)$name /\1/' -e 's/^\(DAEMONS=(.* \)$name \(.*\)/\1\2/' -e 's/^\(DAEMONS=(.*\) $name)/\1)/' -e 's/^\(DAEMONS=(\)$name)/\1)/'"
+                echo "sed -i /etc/rc.conf -e 's/^\\(DAEMONS=(\\)$name /\\1/' -e 's/^\\(DAEMONS=(.* \\)$name \\(.*\\)/\\1\\2/' -e 's/^\\(DAEMONS=(.*\\) $name)/\\1)/' -e 's/^\\(DAEMONS=(\\)$name)/\\1)/'"
             ;;
             debian|ubuntu)
                 echo update-rc.d -f \"$name\" remove

From be670597253d1e713ba79416b2392f51108e4ae7 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 09:27:11 +0100
Subject: [PATCH 84/98] print name, not object (user does not need to see
 python way of things)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/emulator.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 0979182a..6d6050e8 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -125,7 +125,7 @@ class Emulator(object):
         if self.cdist_object.exists:
             if self.cdist_object.parameters != self.parameters:
                 raise cdist.Error("Object %s already exists with conflicting parameters:\n%s: %s\n%s: %s"
-                    % (self.cdist_object, " ".join(self.cdist_object.source), self.cdist_object.parameters, self.object_source, self.parameters)
+                    % (self.cdist_object.name, " ".join(self.cdist_object.source), self.cdist_object.parameters, self.object_source, self.parameters)
             )
         else:
             self.cdist_object.create()

From 46e6ea4308dd95462e74e3292a5754c4e21cdcc0 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 09:27:11 +0100
Subject: [PATCH 85/98] print name, not object (user does not need to see
 python way of things)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/emulator.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 0979182a..6d6050e8 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -125,7 +125,7 @@ class Emulator(object):
         if self.cdist_object.exists:
             if self.cdist_object.parameters != self.parameters:
                 raise cdist.Error("Object %s already exists with conflicting parameters:\n%s: %s\n%s: %s"
-                    % (self.cdist_object, " ".join(self.cdist_object.source), self.cdist_object.parameters, self.object_source, self.parameters)
+                    % (self.cdist_object.name, " ".join(self.cdist_object.source), self.cdist_object.parameters, self.object_source, self.parameters)
             )
         else:
             self.cdist_object.create()

From 67abdb339978f231ce64cf0940ee9e85ba9f59c8 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 12:46:36 +0100
Subject: [PATCH 86/98] +lunchlogfile

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/logs/2012-02-15.steven | 120 +++++++++++++++++++++++++++++++++
 1 file changed, 120 insertions(+)
 create mode 100644 doc/dev/logs/2012-02-15.steven

diff --git a/doc/dev/logs/2012-02-15.steven b/doc/dev/logs/2012-02-15.steven
new file mode 100644
index 00000000..96bccb9f
--- /dev/null
+++ b/doc/dev/logs/2012-02-15.steven
@@ -0,0 +1,120 @@
+- parameter/setting default from manifest
+    - current bug
+    - proposal 1: parameter/default/$name (for optional ones)
+        - new way
+        - catches --state absent|present
+        - needs changes of types
+        - also possible for explorer
+        - support for it in core?
+            - handling of ${o} $o "$o" ?
+            - handling which variables?
+            - introduction of "templating language"
+                - aka macros
+                - possible problems:
+                    - inconsistency
+                    - redoing shell functionality
+                    - raising expectations for more templating from users
+                - possible benefit
+                    - no need for eval
+                    - once in core, not everytime in type
+                        - OTOH: one extra word. 
+                        - a=$(cat $__object/parameter/name) vs. $(eval $(cat $__object/parameter/name))
+        - only possible for static defaults
+            - --name overrides name not possible vs. object_id
+                - Is this the only case????
+                    - if yes: don't care.
+                - possible solution:
+                    - echo '/$__object_id' > typename/parameter/default/name
+                    - eval $(cat $__object/parameter/name)
+                        - probably allows code injection
+                            - is possible anyway???
+                            - $(cat /etc/shadow)
+                        - other eval side effects???
+                            - none: go for it
+                            - some: have headache
+                            - many: don't do
+    - proposal 2: 2 dbs (user input vs. stuff changable by type)
+        - explicit 2nd db [parameter_user and parameter/]
+        - not very clean (both agreed)
+    - proposal 3: parameter are read-only
+        - breaks current types (in core probably elsewhere)
+        - can't enforce, but user is on his own => breaks, her problem
+        + clean seperation between core and type (nico)
+            - parameter belongs to type not core (steven)
+    - proposal 4: core ignores changes in parameter/* of object
+        - implicit 2nd db [see automagic below]
+        - steven+++
+        - does not work with divergent emulator not being in core
+            - because emulators primary db __is__ fs.
+
+1 manifest:
+
+__foo bar == emulator
+echo present > $__global/object/__foo/bar/parameter/state
+
+# fails
+__foo bar == emulator
+
+! automagic / filesystem
+    ! fsproperty:
+        - kill, write explicitly to disk
+
+    - implicit/automatic writes/read to fs
+        - explicit interfaces are better then implicit
+        - same problems as in cdist 1.x to 2.x move! (environment!)
+    - format on disk should not change/dictate code flow
+        - degrade python to shell (nico++! steven--)
+            - user should not care about python, ruby, .net or ASM implementation (steven++ nico++)
+
+    ? proposal 1: diverge emulator / core
+        - emulator verifies input
+        - emulator writes to fs
+        - core reads/syncs from/to fs before passing control to user
+
+    ? proposal 2: emulator is dumb and passes data to core
+        - core creates objects
+        - no fs involved
+        - core reads/syncs from/to fs before passing control to user
+        - passing:
+            - full objects via pickle
+            - parameters only
+            - how???
+                - unix socket?
+                    - not everywhere possible?
+                - tcp / ip
+                    - not everywhere possible
+                        - chroot / local only
+                - rfc 1149
+                    - not everywhere possible
+                        - missing avian carriers
+                - 0mq
+                    - not everywhere possible
+                        - not installed
+                - shm (ipcs and friends)
+                    - not everywhere possible
+                        - no /dev/shm, different libraries? cleanups needed...
+                - what speaks against FS?
+                    - emulator_input/.../
+
+                - nico: to fancy probably
+
+! boolean implementation
+    - nico: 
+        - parameters/boolean: document
+        - argparse changes (consider parameters/boolean)
+            - create 
+    - can be implemented with changes in emulator
+        - use store_true, del if false => never seen by core
+    - INDEPENDENT INDEPENDT OF FS.PROPERTIES!!111111!
+
+- emulator:
+    - how much integrated into core
+        - also: using CdistObject????
+    - dependency on filesystem: good (nico) | bad (steven)
+
+- singleton / support without object_id
+
+
+- logging divergent between emulator / core
+    - no problem (nico)
+    - may be helpful (steven)

From 6ec57acce6fbd52211c95cbb9f4124f8288d741f Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 13:08:29 +0100
Subject: [PATCH 87/98] ++logchanges

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/logs/2012-02-15.steven | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/doc/dev/logs/2012-02-15.steven b/doc/dev/logs/2012-02-15.steven
index 96bccb9f..2d513728 100644
--- a/doc/dev/logs/2012-02-15.steven
+++ b/doc/dev/logs/2012-02-15.steven
@@ -1,4 +1,7 @@
 - parameter/setting default from manifest
+    ==> BRANCH[feature_default_parameters],
+    ==> PERSON[Steven or Nico]
+    ==> PROPOSAL(1)
     - current bug
     - proposal 1: parameter/default/$name (for optional ones)
         - new way
@@ -58,6 +61,9 @@ __foo bar == emulator
 ! automagic / filesystem
     ! fsproperty:
         - kill, write explicitly to disk
+    ==> BRANCH[cleanup_fsproperty]
+    ==> PERSON[Steven]
+    ==> PROPOSAL(just cleanup)
 
     - implicit/automatic writes/read to fs
         - explicit interfaces are better then implicit
@@ -99,6 +105,8 @@ __foo bar == emulator
                 - nico: to fancy probably
 
 ! boolean implementation
+    ==> BRANCH[feature_boolean_parameter]
+    ==> PERSON[Steven]
     - nico: 
         - parameters/boolean: document
         - argparse changes (consider parameters/boolean)
@@ -113,7 +121,11 @@ __foo bar == emulator
     - dependency on filesystem: good (nico) | bad (steven)
 
 - singleton / support without object_id
+    - not discussed
 
+- __apt_ppa:
+    ==> BRANCH[bugfix_do_not_change_state_in_manifest]
+    ==> PERSON[Nico]
 
 - logging divergent between emulator / core
     - no problem (nico)

From ddb5bd16c923c5aabe465115ca1cb0819dde2cc3 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 13:36:05 +0100
Subject: [PATCH 88/98] also support @daemon syntax from rc.conf

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 conf/type/__start_on_boot/gencode-remote | 3 ++-
 doc/dev/todo/niconext                    | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/conf/type/__start_on_boot/gencode-remote b/conf/type/__start_on_boot/gencode-remote
index f1788d4b..be2bd98b 100755
--- a/conf/type/__start_on_boot/gencode-remote
+++ b/conf/type/__start_on_boot/gencode-remote
@@ -58,7 +58,8 @@ case "$state_should" in
         case "$os" in
             archlinux)
                 # Replace a) at the beginning b) in the middle c) end d) only
-                echo "sed -i /etc/rc.conf -e 's/^\\(DAEMONS=(\\)$name /\\1/' -e 's/^\\(DAEMONS=(.* \\)$name \\(.*\\)/\\1\\2/' -e 's/^\\(DAEMONS=(.*\\) $name)/\\1)/' -e 's/^\\(DAEMONS=(\\)$name)/\\1)/'"
+                # Support @name as well...makes it more ugly, but well...
+                echo "sed -i /etc/rc.conf -e 's/^\\(DAEMONS=(\\)@\\{0,1\\}$name /\\1/' -e 's/^\\(DAEMONS=(.* \\)@\\{0,1\\}$name \\(.*\\)/\\1\\2/' -e 's/^\\(DAEMONS=(.*\\) @\\{0,1\\}$name)/\\1)/' -e 's/^\\(DAEMONS=(\\)@\\{0,1\\}$name)/\\1)/'"
             ;;
             debian|ubuntu)
                 echo update-rc.d -f \"$name\" remove
diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index f81c7570..828ff917 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -1,4 +1,4 @@
-2.0.8 features / cleanups:
+- introduce default parameters
 
 - cleanup object_id handling
     - have a look at singletons

From 362bdcdbdddcc013e66d79877c38549f5dc1b8de Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Wed, 15 Feb 2012 13:57:45 +0100
Subject: [PATCH 89/98] implement boolean parameters

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 .../fixtures/conf/type/__arguments_boolean/parameter/boolean    | 2 ++
 .../fixtures/conf/type/__arguments_optional/parameter/optional  | 1 +
 .../fixtures/conf/type/__arguments_required/parameter/required  | 2 ++
 .../type/fixtures/__with_boolean_parameters/parameter/boolean   | 2 ++
 lib/cdist/test/type/fixtures/__without_boolean_parameters/.keep | 0
 5 files changed, 7 insertions(+)
 create mode 100644 lib/cdist/test/emulator/fixtures/conf/type/__arguments_boolean/parameter/boolean
 create mode 100644 lib/cdist/test/emulator/fixtures/conf/type/__arguments_optional/parameter/optional
 create mode 100644 lib/cdist/test/emulator/fixtures/conf/type/__arguments_required/parameter/required
 create mode 100644 lib/cdist/test/type/fixtures/__with_boolean_parameters/parameter/boolean
 create mode 100644 lib/cdist/test/type/fixtures/__without_boolean_parameters/.keep

diff --git a/lib/cdist/test/emulator/fixtures/conf/type/__arguments_boolean/parameter/boolean b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_boolean/parameter/boolean
new file mode 100644
index 00000000..3215c409
--- /dev/null
+++ b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_boolean/parameter/boolean
@@ -0,0 +1,2 @@
+boolean1
+boolean2
diff --git a/lib/cdist/test/emulator/fixtures/conf/type/__arguments_optional/parameter/optional b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_optional/parameter/optional
new file mode 100644
index 00000000..31647628
--- /dev/null
+++ b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_optional/parameter/optional
@@ -0,0 +1 @@
+optional1
diff --git a/lib/cdist/test/emulator/fixtures/conf/type/__arguments_required/parameter/required b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_required/parameter/required
new file mode 100644
index 00000000..e0fba2c9
--- /dev/null
+++ b/lib/cdist/test/emulator/fixtures/conf/type/__arguments_required/parameter/required
@@ -0,0 +1,2 @@
+required1
+required2
diff --git a/lib/cdist/test/type/fixtures/__with_boolean_parameters/parameter/boolean b/lib/cdist/test/type/fixtures/__with_boolean_parameters/parameter/boolean
new file mode 100644
index 00000000..3215c409
--- /dev/null
+++ b/lib/cdist/test/type/fixtures/__with_boolean_parameters/parameter/boolean
@@ -0,0 +1,2 @@
+boolean1
+boolean2
diff --git a/lib/cdist/test/type/fixtures/__without_boolean_parameters/.keep b/lib/cdist/test/type/fixtures/__without_boolean_parameters/.keep
new file mode 100644
index 00000000..e69de29b

From 0760ff3c94edefc815697caae1807ae7894771c0 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Wed, 15 Feb 2012 14:44:16 +0100
Subject: [PATCH 90/98] implement boolean parameters, forgotten files ;-)

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 lib/cdist/core/cdist_type.py        | 17 +++++++++
 lib/cdist/emulator.py               |  5 ++-
 lib/cdist/test/emulator/__init__.py | 58 ++++++++++++++++++++++++++++-
 lib/cdist/test/type/__init__.py     | 11 ++++++
 4 files changed, 89 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/core/cdist_type.py b/lib/cdist/core/cdist_type.py
index 55609e7e..1d2472c4 100644
--- a/lib/cdist/core/cdist_type.py
+++ b/lib/cdist/core/cdist_type.py
@@ -82,6 +82,7 @@ class CdistType(object):
         self.__explorers = None
         self.__required_parameters = None
         self.__optional_parameters = None
+        self.__boolean_parameters = None
 
     def __repr__(self):
         return '<CdistType %s>' % self.name
@@ -144,3 +145,19 @@ class CdistType(object):
             finally:
                 self.__optional_parameters = parameters
         return self.__optional_parameters
+
+    @property
+    def boolean_parameters(self):
+        """Return a list of boolean parameters"""
+        if not self.__boolean_parameters:
+            parameters = []
+            try:
+                with open(os.path.join(self.absolute_path, "parameter", "boolean")) as fd:
+                    for line in fd:
+                        parameters.append(line.strip())
+            except EnvironmentError:
+                # error ignored
+                pass
+            finally:
+                self.__boolean_parameters = parameters
+        return self.__boolean_parameters
diff --git a/lib/cdist/emulator.py b/lib/cdist/emulator.py
index 6d6050e8..c4b84feb 100644
--- a/lib/cdist/emulator.py
+++ b/lib/cdist/emulator.py
@@ -87,7 +87,7 @@ class Emulator(object):
     def commandline(self):
         """Parse command line"""
 
-        parser = argparse.ArgumentParser(add_help=False)
+        parser = argparse.ArgumentParser(add_help=False, argument_default=argparse.SUPPRESS)
 
         for parameter in self.cdist_type.optional_parameters:
             argument = "--" + parameter
@@ -95,6 +95,9 @@ class Emulator(object):
         for parameter in self.cdist_type.required_parameters:
             argument = "--" + parameter
             parser.add_argument(argument, dest=parameter, action='store', required=True)
+        for parameter in self.cdist_type.boolean_parameters:
+            argument = "--" + parameter
+            parser.add_argument(argument, dest=parameter, action='store_const', const='')
 
         # If not singleton support one positional parameter
         if not self.cdist_type.is_singleton:
diff --git a/lib/cdist/test/emulator/__init__.py b/lib/cdist/test/emulator/__init__.py
index f1ea5832..370d3d82 100644
--- a/lib/cdist/test/emulator/__init__.py
+++ b/lib/cdist/test/emulator/__init__.py
@@ -126,7 +126,7 @@ class AutoRequireEmulatorTestCase(test.CdistTestCase):
         self.assertEqual(sorted(cdist_object.requirements), sorted(expected))
 
 
-class ArgumentsWithDashesTestCase(test.CdistTestCase):
+class ArgumentsTestCase(test.CdistTestCase):
 
     def setUp(self):
         self.temp_dir = self.mkdtemp()
@@ -159,3 +159,59 @@ class ArgumentsWithDashesTestCase(test.CdistTestCase):
         cdist_type = core.CdistType(self.local.type_path, '__arguments_with_dashes')
         cdist_object = core.CdistObject(cdist_type, self.local.object_path, 'some-id')
         self.assertTrue('with-dash' in cdist_object.parameters)
+
+    def test_boolean(self):
+        type_name = '__arguments_boolean'
+        object_id = 'some-id'
+        argv = [type_name, object_id, '--boolean1']
+        os.environ.update(self.env)
+        emu = emulator.Emulator(argv)
+        emu.run()
+
+        cdist_type = core.CdistType(self.local.type_path, type_name)
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, object_id)
+        self.assertTrue('boolean1' in cdist_object.parameters)
+        self.assertFalse('boolean2' in cdist_object.parameters)
+        # empty file -> True
+        self.assertTrue(cdist_object.parameters['boolean1'] == '')
+
+    def test_required(self):
+        type_name = '__arguments_required'
+        object_id = 'some-id'
+        value = 'some value'
+        argv = [type_name, object_id, '--required1', value, '--required2', value]
+        os.environ.update(self.env)
+        emu = emulator.Emulator(argv)
+        emu.run()
+
+        cdist_type = core.CdistType(self.local.type_path, type_name)
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, object_id)
+        self.assertTrue('required1' in cdist_object.parameters)
+        self.assertTrue('required2' in cdist_object.parameters)
+        self.assertEqual(cdist_object.parameters['required1'], value)
+        self.assertEqual(cdist_object.parameters['required2'], value)
+
+#    def test_required_missing(self):
+#        type_name = '__arguments_required'
+#        object_id = 'some-id'
+#        value = 'some value'
+#        argv = [type_name, object_id, '--required1', value]
+#        os.environ.update(self.env)
+#        emu = emulator.Emulator(argv)
+#        
+#        self.assertRaises(SystemExit, emu.run)
+
+    def test_optional(self):
+        type_name = '__arguments_optional'
+        object_id = 'some-id'
+        value = 'some value'
+        argv = [type_name, object_id, '--optional1', value]
+        os.environ.update(self.env)
+        emu = emulator.Emulator(argv)
+        emu.run()
+
+        cdist_type = core.CdistType(self.local.type_path, type_name)
+        cdist_object = core.CdistObject(cdist_type, self.local.object_path, object_id)
+        self.assertTrue('optional1' in cdist_object.parameters)
+        self.assertFalse('optional2' in cdist_object.parameters)
+        self.assertEqual(cdist_object.parameters['optional1'], value)
diff --git a/lib/cdist/test/type/__init__.py b/lib/cdist/test/type/__init__.py
index 2ef14a4c..5e774aa9 100644
--- a/lib/cdist/test/type/__init__.py
+++ b/lib/cdist/test/type/__init__.py
@@ -145,3 +145,14 @@ class TypeTestCase(test.CdistTestCase):
         base_path = fixtures
         cdist_type = core.CdistType(base_path, '__without_optional_parameters')
         self.assertEqual(cdist_type.optional_parameters, [])
+
+    def test_with_boolean_parameters(self):
+        base_path = fixtures
+        cdist_type = core.CdistType(base_path, '__with_boolean_parameters')
+        self.assertEqual(cdist_type.boolean_parameters, ['boolean1', 'boolean2'])
+
+    def test_without_boolean_parameters(self):
+        base_path = fixtures
+        cdist_type = core.CdistType(base_path, '__without_boolean_parameters')
+        self.assertEqual(cdist_type.boolean_parameters, [])
+

From a4882e7e30a40c453735f4e727f267a9e759dcd8 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 16:17:49 +0100
Subject: [PATCH 91/98] remove useless script printing and reuse run() method

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/dev/todo/niconext    |  3 ---
 lib/cdist/exec/local.py  | 21 +--------------------
 lib/cdist/exec/remote.py | 28 ++--------------------------
 3 files changed, 3 insertions(+), 49 deletions(-)

diff --git a/doc/dev/todo/niconext b/doc/dev/todo/niconext
index 828ff917..bead6d72 100644
--- a/doc/dev/todo/niconext
+++ b/doc/dev/todo/niconext
@@ -3,9 +3,6 @@
 - cleanup object_id handling
     - have a look at singletons
 
-- remove useless
-    ERROR: monitoring02: Code that raised the error:
-
 - ensure that all types, which support --state support
     present and absent (consistent look and feel)
 
diff --git a/lib/cdist/exec/local.py b/lib/cdist/exec/local.py
index cdf06205..e24ae484 100644
--- a/lib/cdist/exec/local.py
+++ b/lib/cdist/exec/local.py
@@ -119,26 +119,7 @@ class Local(object):
         command = ["/bin/sh", "-e"]
         command.append(script)
 
-        self.log.debug("Local run script: %s", command)
-
-        if env is None:
-            env = os.environ.copy()
-        # Export __target_host for use in __remote_{copy,exec} scripts
-        env['__target_host'] = self.target_host
-
-        self.log.debug("Local run script env: %s", env)
-
-        try:
-            if return_output:
-                return subprocess.check_output(command, env=env).decode()
-            else:
-                subprocess.check_call(command, env=env)
-        except subprocess.CalledProcessError as error:
-            script_content = self.run(["cat", script], return_output=True)
-            self.log.error("Code that raised the error:\n%s", script_content)
-            raise LocalScriptError(script, command, script_content)
-        except EnvironmentError as error:
-            raise cdist.Error(" ".join(command) + ": " + error.args[1])
+        self.run(command, env, return_output)
 
     def link_emulator(self, exec_path):
         """Link emulator to types"""
diff --git a/lib/cdist/exec/remote.py b/lib/cdist/exec/remote.py
index 69dc5dda..0fb93e10 100644
--- a/lib/cdist/exec/remote.py
+++ b/lib/cdist/exec/remote.py
@@ -139,32 +139,8 @@ class Remote(object):
         Return the output as a string.
 
         """
-        command = self._exec.split()
-        command.append(self.target_host)
 
-        # export target_host for use in __remote_{exec,copy} scripts
-        os_environ = os.environ.copy()
-        os_environ['__target_host'] = self.target_host
-
-        self.log.debug("Remote run script: %s", command)
-
-        # can't pass environment to remote side, so prepend command with
-        # variable declarations
-        if env:
-            self.log.debug("Remote run script env: %s", env)
-            command.extend(["%s=%s" % item for item in env.items()])
-
-        command.extend(["/bin/sh", "-e"])
+        command = ["/bin/sh", "-e"]
         command.append(script)
 
-        try:
-            if return_output:
-                return subprocess.check_output(command, env=os_environ).decode()
-            else:
-                subprocess.check_call(command, env=os_environ)
-        except subprocess.CalledProcessError as error:
-            script_content = self.run(["cat", script], return_output=True)
-            self.log.error("Code that raised the error:\n%s", script_content)
-            raise RemoteScriptError(script, command, script_content)
-        except EnvironmentError as error:
-            raise cdist.Error(" ".join(command) + ": " + error.args[1])
+        self.run(command, env, return_output)

From ab48a72ce135df073b3be572e8fe24bcc6296421 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 16:25:18 +0100
Subject: [PATCH 92/98] return results from run()

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/exec/local.py  | 2 +-
 lib/cdist/exec/remote.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/cdist/exec/local.py b/lib/cdist/exec/local.py
index e24ae484..7fb63429 100644
--- a/lib/cdist/exec/local.py
+++ b/lib/cdist/exec/local.py
@@ -119,7 +119,7 @@ class Local(object):
         command = ["/bin/sh", "-e"]
         command.append(script)
 
-        self.run(command, env, return_output)
+        return self.run(command, env, return_output)
 
     def link_emulator(self, exec_path):
         """Link emulator to types"""
diff --git a/lib/cdist/exec/remote.py b/lib/cdist/exec/remote.py
index 0fb93e10..47b670b0 100644
--- a/lib/cdist/exec/remote.py
+++ b/lib/cdist/exec/remote.py
@@ -143,4 +143,4 @@ class Remote(object):
         command = ["/bin/sh", "-e"]
         command.append(script)
 
-        self.run(command, env, return_output)
+        return self.run(command, env, return_output)

From f031a40746c30beec6ccdc4d282a475ff9bb9eb6 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 17:01:03 +0100
Subject: [PATCH 93/98] rebuild the command string

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/exec/remote.py | 49 ++++++++++++++++------------------------
 1 file changed, 19 insertions(+), 30 deletions(-)

diff --git a/lib/cdist/exec/remote.py b/lib/cdist/exec/remote.py
index 47b670b0..7cd9052d 100644
--- a/lib/cdist/exec/remote.py
+++ b/lib/cdist/exec/remote.py
@@ -28,17 +28,6 @@ import logging
 
 import cdist
 
-
-class RemoteScriptError(cdist.Error):
-    def __init__(self, script, command, script_content):
-        self.script = script
-        self.command = command
-        self.script_content = script_content
-
-    def __str__(self):
-        plain_command = " ".join(self.command)
-        return "Remote script execution failed: %s" % plain_command
-
 class DecodeError(cdist.Error):
     def __init__(self, command):
         self.command = command
@@ -91,6 +80,17 @@ class Remote(object):
         command.extend(["-r", source, self.target_host + ":" + destination])
         self._run_command(command)
 
+    def run_script(self, script, env=None, return_output=False):
+        """Run the given script with the given environment on the remote side.
+        Return the output as a string.
+
+        """
+
+        command = ["/bin/sh", "-e"]
+        command.append(script)
+
+        return self.run(command, env, return_output)
+
     def run(self, command, env=None, return_output=False):
         """Run the given command with the given environment on the remote side.
         Return the output as a string.
@@ -99,7 +99,15 @@ class Remote(object):
         # prefix given command with remote_exec
         cmd = self._exec.split()
         cmd.append(self.target_host)
+
+        # can't pass environment to remote side, so prepend command with
+        # variable declarations
+        if env:
+            remote_env = ["%s=%s" % item for item in env.items()]
+            cmd.append(remote_env)
+
         cmd.extend(command)
+
         return self._run_command(cmd, env=env, return_output=return_output)
 
     def _run_command(self, command, env=None, return_output=False):
@@ -113,14 +121,6 @@ class Remote(object):
         os_environ = os.environ.copy()
         os_environ['__target_host'] = self.target_host
 
-        # can't pass environment to remote side, so prepend command with
-        # variable declarations
-        if env:
-            cmd = ["%s=%s" % item for item in env.items()]
-            cmd.extend(command)
-        else:
-            cmd = command
-
         self.log.debug("Remote run: %s", command)
         try:
             if return_output:
@@ -133,14 +133,3 @@ class Remote(object):
             raise cdist.Error(" ".join(*args) + ": " + error.args[1])
         except UnicodeDecodeError:
             raise DecodeError(command)
-
-    def run_script(self, script, env=None, return_output=False):
-        """Run the given script with the given environment on the remote side.
-        Return the output as a string.
-
-        """
-
-        command = ["/bin/sh", "-e"]
-        command.append(script)
-
-        return self.run(command, env, return_output)

From 72fb77f13552bc5fbc240e8c584c94cc4b3ce16c Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 17:02:21 +0100
Subject: [PATCH 94/98] extend not append

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/exec/remote.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cdist/exec/remote.py b/lib/cdist/exec/remote.py
index 7cd9052d..124c1b4f 100644
--- a/lib/cdist/exec/remote.py
+++ b/lib/cdist/exec/remote.py
@@ -104,7 +104,7 @@ class Remote(object):
         # variable declarations
         if env:
             remote_env = ["%s=%s" % item for item in env.items()]
-            cmd.append(remote_env)
+            cmd.extend(remote_env)
 
         cmd.extend(command)
 

From 64bb1741aa0fb201b5e0f683f607f05c534a7038 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 17:05:22 +0100
Subject: [PATCH 95/98] cleanup local

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 lib/cdist/exec/local.py | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/lib/cdist/exec/local.py b/lib/cdist/exec/local.py
index 7fb63429..d3c6a0ce 100644
--- a/lib/cdist/exec/local.py
+++ b/lib/cdist/exec/local.py
@@ -32,18 +32,6 @@ import logging
 import cdist
 from cdist import core
 
-
-class LocalScriptError(cdist.Error):
-    def __init__(self, script, command, script_content):
-        self.script = script
-        self.command = command
-        self.script_content = script_content
-
-    def __str__(self):
-        plain_command = " ".join(self.command)
-        return "Local script execution failed: %s" % plain_command
-
-
 class Local(object):
     """Execute commands locally.
 
@@ -131,4 +119,4 @@ class Local(object):
             try:
                 os.symlink(src, dst)
             except OSError as e:
-                raise cdist.Error("Linking emulator from " + src + " to " + dst + " failed: " + e.__str__())
+                raise cdist.Error("Linking emulator from %s to %s failed: %s" % (src, dst, e.__str__()))

From 4a844ef2650314ed995608c5150e9cdf5121afb6 Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Wed, 15 Feb 2012 17:06:58 +0100
Subject: [PATCH 96/98] ++changes(2.0.8)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/changelog | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/changelog b/doc/changelog
index 2d2d7a48..507726bc 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -6,6 +6,7 @@ Changelog
 
 2.0.8:
 	* Cleanup: Better hint to source of error
+	* Cleanup: Do not output failing script, but path to script only
 	* Cleanup: Remove support for __debug variable in manifests (Type != Core
 		debugging)
 

From 79dedb5bb52cd856ecef5e12340e2c38a42bf0a0 Mon Sep 17 00:00:00 2001
From: Steven Armstrong <steven@icarus.ethz.ch>
Date: Thu, 16 Feb 2012 10:17:09 +0100
Subject: [PATCH 97/98] document boolean parameters

Signed-off-by: Steven Armstrong <steven@icarus.ethz.ch>
---
 doc/man/cdist-reference.text.sh |  7 ++++--
 doc/man/man7/cdist-type.text    | 41 +++++++++++++++++++++++++++------
 2 files changed, 39 insertions(+), 9 deletions(-)

diff --git a/doc/man/cdist-reference.text.sh b/doc/man/cdist-reference.text.sh
index 81e58ab2..a76e7941 100755
--- a/doc/man/cdist-reference.text.sh
+++ b/doc/man/cdist-reference.text.sh
@@ -101,12 +101,15 @@ conf/type/<name>/gencode-local::
 conf/type/<name>/gencode-remote::
     Used to generate code to be executed on the client.
 
-conf/type/<name>/parameters/required::
+conf/type/<name>/parameter/required::
     Parameters required by type, \n seperated list.
 
-conf/type/<name>/parameters/optional::
+conf/type/<name>/parameter/optional::
     Parameters optionally accepted by type, \n seperated list.
 
+conf/type/<name>/parameter/boolean::
+   Boolean parameters accepted by type, \n seperated list.
+
 conf/type/<name>/explorer::
     Location of the type specific explorers.
     This directory is referenced by the variable __type_explorer (see below).
diff --git a/doc/man/man7/cdist-type.text b/doc/man/man7/cdist-type.text
index 48d412f1..1147511e 100644
--- a/doc/man/man7/cdist-type.text
+++ b/doc/man/man7/cdist-type.text
@@ -40,7 +40,7 @@ A list of supported types can be found in the cdist-reference(7) manpage.
 
 SINGLETON TYPES
 ---------------
-If a type is flagged as a singleton, it may be used only 
+If a type is flagged as a singleton, it may be used only
 once per host. This is useful for types which can be used only once on a
 system. Singleton types do not take an object name as argument.
 
@@ -72,15 +72,42 @@ To begin a new type, just create the directory **conf/type/__NAME**.
 
 DEFINING PARAMETERS
 -------------------
-Every type consists of optional and required parameters, which must
-be created in a newline seperated file in ***parameters/required*** and
-***parameters/optional***. If either or both missing, the type will have
-no required, no optional or no parameters at all.
+Every type consists of required, optional and boolean parameters, which must
+be created in a newline seperated file in ***parameter/required***,
+***parameter/optional*** and ***parameter/boolean***. If either is missing,
+the type will have no required, no optional, no boolean or no parameters at
+all.
 
 Example:
 --------------------------------------------------------------------------------
 echo servername >> conf/type/__nginx_vhost/parameter/required
 echo logdirectory >> conf/type/__nginx_vhost/parameter/optional
+echo use_ssl >> conf/type/__nginx_vhost/parameter/boolean
+--------------------------------------------------------------------------------
+
+
+USING PARAMETERS
+----------------
+The parameters given to a type can be accessed and used in all type scripts
+(e.g manifest, gencode-*, explorer/*). Note that boolean parameters are
+represented by file existence. File exists -> True,
+file does not exist -> False
+
+Example: (e.g. in conf/type/__nginx_vhost/manifest)
+--------------------------------------------------------------------------------
+# required parameter
+servername="$(cat "$__object/parameter/servername")"
+
+# optional parameter
+if [ -f "$__object/parameter/logdirectory" ]; then
+   logdirectory="$(cat "$__object/parameter/logdirectory")"
+fi
+
+# boolean parameter
+if [ -f "$__object/parameter/use_ssl" ]; then
+   # file exists -> True
+   # do some fancy ssl stuff
+fi
 --------------------------------------------------------------------------------
 
 
@@ -116,7 +143,7 @@ SINGLETON - ONLY INSTANCE ONLY
 ------------------------------
 If you want to ensure that a type can only be used once per target, you can
 mark it as a singleton: Just create the (empty) file "singleton" in your type
-directory: 
+directory:
 
 --------------------------------------------------------------------------------
 touch conf/type/__NAME/singleton
@@ -128,7 +155,7 @@ This will also change the way your type must be called:
 __YOURTYPE --parameter value
 --------------------------------------------------------------------------------
 
-As you can see, the object ID is omitted, because it does not make any sense, 
+As you can see, the object ID is omitted, because it does not make any sense,
 if your type can be used only once.
 
 

From baf8614e6cfab4467a62c57c66f82cd4940939ee Mon Sep 17 00:00:00 2001
From: Nico Schottelius <nico@brief.schottelius.org>
Date: Thu, 16 Feb 2012 11:13:50 +0100
Subject: [PATCH 98/98] ++changes(2.0.8)

Signed-off-by: Nico Schottelius <nico@brief.schottelius.org>
---
 doc/changelog | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/changelog b/doc/changelog
index 507726bc..ab006435 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -9,6 +9,7 @@ Changelog
 	* Cleanup: Do not output failing script, but path to script only
 	* Cleanup: Remove support for __debug variable in manifests (Type != Core
 		debugging)
+	* Feature Core: Support boolean parameters (Steven Armstrong)
 
 2.0.7: 2012-02-13
 	* Bugfix __file: Use chmod after chown/chgrp (Matt Coddington)