[Mono-docs-list] [Monodoc Patch] Implementation of a command line installer for monodoc.

Hector E. Gomez Morales hgomez_36@flashmail.com
Mon, 25 Oct 2004 17:32:08 +0000


This is a MIME-formatted message.  If you see this text it means that your
E-mail software does not support MIME-formatted messages.

--=_galadriel.fciencias.unam.mx-32541-1098746825-0001-2
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 7bit

To install new documentation inside Monodoc one has to modify
monodoc.xml and create a corresponding node, then create a source file
for the documentation and finally copy the source file, zip file and
tree file inside the sources directory in monodoc path or if you had cvs
access insert you node inside monodoc.xml.

This approach is not so nice for third party, internal or home made
libraries from developers that want to install his documentation and see
it in monodoc, because of that I made a commandline tool that automates
the creation of the node in monodoc.xml, the creation of the source file
and finally the install of the .zip, .source and .tree to sources.
The restrictions of this tool are this:

The installer has to run in the same directoy as the .zip and .tree.A
path param could be implemented but I think is overkill.

The installer takes for granted that the documentation is going to use
the ecma provider so no xhtml, man , etc support for now, it is easy to
add a param to take the provider needed for the docs.

Attached is a diff of the building process to add installer.exe
The other file is the source of the program and have to be put in the
directory browser of the module of monodoc.

The normal use of the tool is as follows:
For installation:
monodoc --install <label> <package> [<parent>]

where label is the name of the node that is appears in the treeview of
monodoc
where package is the name of the documentation ie you have
microsoft-jscript.tree and microsoft-jscript.source files then the name
is microsoft-jscript.

where parent is the name of a node in monodoc.xml and from there the new
doc node is append.

For uninstallation:
monodoc --uninstall <package>

where package is the same has in installation ie the name prefix of
the .zip and .tree files.

I Think I have cached all the obvious points of errors, I will like to
be granted permission to cvs commit this patch, it is pretty functional
and is certain mode necessary.

Hector

--=_galadriel.fciencias.unam.mx-32541-1098746825-0001-2
Content-Type: text/x-csharp; name="installer.cs"; charset=utf-8
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=installer.cs

//
// installer.cs: Monodoc documentation installer.
//
// Author:
//   Hector Gomez M.
//
//
using System;
using System.IO;
using System.Xml;
using System.Reflection;

namespace MonoDoc
{
	public class Installer
	{
		static string base_path;
		static string config;
		static bool alt_parent;
		static string def_parent = "various";
		
		static void Usage()
		{
			Console.WriteLine("Usage: mono installer.exe --add | --del");
			Console.WriteLine("   --add <label> <package> [<parent>]");
			Console.WriteLine("   --del <package>");
			Environment.Exit(1);
		}

		public static void Main (string [] args)
		{
			if (args.Length == 0 || args.Length == 1 || args.Length > 4)
				Usage();
			
			if (args.Length == 4)
				alt_parent = true;
			else
				alt_parent = false;

			// Get monodoc doc path to access monodoc.xml
			base_path = GetDocPath();
			config = base_path + "/monodoc.xml";

			XmlDocument doc = new XmlDocument();
			doc = ReadConfig(config);

			switch(args[0]){
				case "--add":
					if (!(args.Length == 2)){
						if (!alt_parent){
							Install(doc, args[1], def_parent, args[2]);
						} else {
							Install(doc, args[1], args[3], args[2]);
						}
					} else {
						Usage();
						Environment.Exit(1);
					}
					break;

				case "--del":
					Uninstall(doc, args[1]);
					break;
				
				default:
					Usage();
					break;
			}
		}

		static string GetDocPath()
		{
			Assembly assm = Assembly.LoadWithPartialName("monodoc");
			string cfg_file = assm.Location + ".config";

			XmlDocument doc = new XmlDocument ();
			try {
				doc.Load (cfg_file);
			} catch (FileNotFoundException e){
				Console.WriteLine("Error: No monodoc.dll.config found, missing or broken installation of monodoc.");
				Environment.Exit(1);
			}

			XmlNode root = doc.DocumentElement;
			base_path = root.SelectSingleNode ("/config/path").Attributes ["docsPath"].Value;
			return base_path;
		}

		static void Install (XmlDocument doc, string label, string parent_name, string package_name){
			if (PreviousInstall(doc, package_name)){
				Console.WriteLine("Error: Previous install of " + package_name + " detected.");
				Environment.Exit(1);
			}

			//Create package source file.
			CreateSource("ecma", package_name);

			//Copy files to the doc path.
			CopyDoc(package_name, base_path);

			// Create node.
			CreateNode(doc, label, parent_name, package_name);

			// Save modified monodoc.xml.
			WriteConfig(doc, config);
			Console.WriteLine("Documentation install of " + package_name + " successful.");
		}

		static void CreateNode (XmlDocument doc, string label, string parent_name, string package_name)
		{
			XmlNode root = doc.DocumentElement;
			XmlNode node = root.SelectSingleNode("//node[@name='" + parent_name + "']");

			if (node == null){
				Console.WriteLine("Error: No parent with name " + parent_name + " was found.");
				DeleteDoc(package_name, base_path);
				Environment.Exit(1);
			}

			XmlElement elem = doc.CreateElement("node");
			XmlAttribute attr = doc.CreateAttribute("label");
			attr.Value = label;
			elem.SetAttributeNode(attr);
			attr = doc.CreateAttribute("name");
			attr.Value = "classlib-" + package_name;
			elem.SetAttributeNode(attr);
			if (parent_name == "root:")
				root.InsertBefore(elem, root.SelectSingleNode("//node[@name='various']"));
			else 
				node.AppendChild(elem);
		}

		static XmlDocument ReadConfig (string filename)
		{
			XmlDocument document = new XmlDocument();
			// Read monodoc.xml file.
			try {
				XmlTextReader reader = new XmlTextReader(filename);
				document.Load(reader);
				reader.Close();
			} catch (FileNotFoundException e){
				Console.WriteLine("Error: No monodoc.xml found, missing or broken installation of monodoc.");
				Environment.Exit(1);
			}
			
			return document;
		}

		static void WriteConfig (XmlDocument doc, string filename)
		{
			XmlTextWriter writer = new XmlTextWriter(filename, null);
			writer.Formatting = Formatting.Indented;
			doc.WriteTo(writer);
			writer.WriteString("\n");
			writer.Close();
		}

		static void CreateSource (string provider, string package_name)
		{
			XmlDocument doc = new XmlDocument();
			XmlNode dec = doc.CreateXmlDeclaration("1.0", null, null);
			doc.AppendChild(dec);
			
			XmlElement root = doc.CreateElement("monodoc");
			doc.AppendChild(root);
			
			XmlElement elem = doc.CreateElement("source");
			XmlAttribute attr = doc.CreateAttribute("provider");
			attr.Value = provider;
			elem.SetAttributeNode(attr);
			attr = doc.CreateAttribute("basefile");
			attr.Value = package_name;
			elem.SetAttributeNode(attr);
			attr = doc.CreateAttribute("path");
			attr.Value = "classlib-" + package_name;
			elem.SetAttributeNode(attr);
			root.AppendChild(elem);

			WriteConfig(doc, package_name + ".source");
		}

		static void CopyDoc (string package_name, string base_path)
		{
			string final_path = base_path + "/sources/";
			try {
				File.Copy(package_name + ".source", final_path + package_name + ".source", true);
				File.Copy(package_name + ".zip", final_path + package_name + ".zip", true);
				File.Copy(package_name + ".tree", final_path + package_name + ".tree", true);
			} catch (FileNotFoundException e){
				File.Delete(final_path + package_name + ".source");
				File.Delete(final_path + package_name + ".zip");
				File.Delete(final_path + package_name + ".tree");
				Console.WriteLine("Error: Missing tree, zip or source file.");
				Environment.Exit(1);
			}				
		}

		static void Uninstall (XmlDocument doc, string package_name)
		{
			DeleteNode(doc, package_name);
			WriteConfig(doc, config);
			DeleteDoc(package_name, base_path);
			Console.WriteLine("Documentation uninstall of " + package_name + " successful.");
		}

		static void DeleteNode (XmlDocument doc, string package_name)
		{
			XmlNode root = doc.DocumentElement;
			try {
				XmlNode node = root.SelectSingleNode("//node[@name='classlib-" + package_name + "']"); 
				XmlNode parent = node.ParentNode;
				parent.RemoveChild(node);
			} catch (NullReferenceException e){
				Console.WriteLine("Error: No " + package_name + " documentation installed.");
				Environment.Exit(1);
			}
		}

		static void DeleteDoc (string package_name, string base_path)
		{
			string final_path = base_path + "/sources/";

			try {
				File.Delete(final_path + package_name + ".source");
				File.Delete(final_path + package_name + ".zip");
				File.Delete(final_path + package_name + ".tree");
			} catch (FileNotFoundException e){
				Console.WriteLine("Error: Deletion of documentation failed");
			}
		}
		
		static bool PreviousInstall (XmlDocument doc, string package_name)
		{
			XmlNode root = doc.DocumentElement;
			XmlNode node = root.SelectSingleNode("//node[@name='classlib-" + package_name + "']");

			if (node == null)
				return false;
			else
				return true;
		}
	}
}

--=_galadriel.fciencias.unam.mx-32541-1098746825-0001-2
Content-Type: text/x-patch; name="monodoc-installer.diff"; charset=utf-8
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=monodoc-installer.diff

? monodoc-installer.diff
? browser/assembler.exe.mdb
? browser/browser.exe.mdb
? browser/installer.cs
? browser/monodoc.dll.mdb
? generator/updater.exe.mdb
? po/POTFILES
? tools/monodocer.exe.mdb
Index: monodoc.in
===================================================================
RCS file: /cvs/public/monodoc/monodoc.in,v
retrieving revision 1.13
diff -u -r1.13 monodoc.in
--- monodoc.in	25 Aug 2004 19:16:39 -0000	1.13
+++ monodoc.in	24 Oct 2004 05:02:13 -0000
@@ -32,6 +32,14 @@
     shift;
     exec mono $monodocdir/validate.exe "$@"
     ;;
+    x--install)
+    shift;
+    exec mono $monodocdir/installer.exe --add "$@"
+    ;;
+    x--uninstall)
+    shift;
+    exec mono $monodocdir/installer.exe --del "$@"
+    ;;
     x--help)
 	echo "Usage is:"
 	echo "monodoc [options]"
@@ -46,6 +54,8 @@
 	echo "  --merge-changes CHANGE_FILE [TARGET_DIR]"
 	echo "  --normalize		format a documentation file consistently"
 	echo "  --validate		validate the xml file(s)"
+	echo "  --install               install a documentation package"
+	echo "  --uninstall		uninstall a documentation package"
 	echo "  TOPIC			display the browser at TOPIC (ex. N:System)"
 	exit 0
 	;;
Index: browser/Makefile.am
===================================================================
RCS file: /cvs/public/monodoc/browser/Makefile.am,v
retrieving revision 1.65
diff -u -r1.65 Makefile.am
--- browser/Makefile.am	25 Aug 2004 20:46:31 -0000	1.65
+++ browser/Makefile.am	24 Oct 2004 05:02:28 -0000
@@ -1,7 +1,7 @@
 assemblydir = $(libdir)
-monodoc_DATA = browser.exe assembler.exe normalize.exe monodoc.xml mod.exe validate.exe
+monodoc_DATA = browser.exe assembler.exe normalize.exe monodoc.xml mod.exe validate.exe installer.exe
 noinst_DATA = monodoc.dll monodoc.dll.config
-CLEANFILES = monodoc.dll assembler.exe browser.exe normalize.exe mod.exe validate.exe
+CLEANFILES = monodoc.dll assembler.exe browser.exe normalize.exe mod.exe validate.exe installer.exe
 DISTCLEANFILE = AssemblyInfo.cs
 CSC=mcs
 
@@ -45,18 +45,21 @@
 validate_sources = \
 	$(srcdir)/validate.cs
 
+installer_sources = \
+	 $(srcdir)/installer.cs
+
 browser_assemblies = -pkg:gtkhtml-sharp -pkg:glade-sharp -r:System.Web.Services
 
 EXTRA_DIST = \
 	$(monodoc_sources) $(assembler_sources) \
 	$(dump_sources) $(browser_sources) 	\
-	$(validate_sources) monodoc-ecma.xsd	\
-	browser.glade monodoc.xml mono-ecma.xsl	\
-	normalize.cs monodoc.dll.config.in	\
-	ecmaspec-html.xsl mod.cs		\
-	AssemblyInfo.cs.in
+	$(validate_sources) $(validate_sources) \
+	monodoc-ecma.xsd browser.glade		\
+	monodoc.xml mono-ecma.xsl normalize.cs 	\
+	monodoc.dll.config.in ecmaspec-html.xsl \
+	mod.cs AssemblyInfo.cs.in
 
-monodoc_FILES = browser.exe assembler.exe normalize.exe admin.exe validate.exe
+monodoc_FILES = browser.exe assembler.exe normalize.exe admin.exe validate.exe installer.exe
 
 assembler.exe: $(assembler_sources) monodoc.dll
 	$(CSC) /debug /out:assembler.exe $(assembler_sources) -r:ICSharpCode.SharpZipLib.dll -r:./monodoc.dll
@@ -75,6 +78,9 @@
 
 validate.exe: validate.cs $(srcdir)/monodoc-ecma.xsd
 	$(CSC) $(srcdir)/validate.cs -out:validate.exe /resource:$(srcdir)/monodoc-ecma.xsd,monodoc-ecma.xsd
+
+installer.exe: installer.cs
+	$(CSC) $(srcdir)/installer.cs -out:installer.exe
 
 mono.pub: $(top_srcdir)/mono.pub
 	cp $(top_srcdir)/mono.pub .

--=_galadriel.fciencias.unam.mx-32541-1098746825-0001-2--