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

Hector E. Gomez Morales hgomez_36@flashmail.com
Tue, 26 Oct 2004 04:04:01 +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-54994-1098781226-0001-2
Content-Type: text/plain; charset=iso-8859-1
Content-Transfer-Encoding: 7bit

Hi

A revised installler.cs many modifications suggested by Cesar.


On Tue, 2004-10-26 at 02:50 +0000, Hector E. Gomez Morales wrote:
> Hi Miguel
> 
> For the core and mayor mono projects the method of asking request for a
> node and/or hierarchy is enough, but for like I said third party
> proyects or homemade it isn't enough.
> 
> I think one way to maintain order and coherence is to have a base
> hierarchy (thinking like a gnome-menu type) where the various node is
> splitted to several nodes like: GUI API, Multimedia API, etc then you
> add the documentation to the right node. Flexibility and order ;).
> 
> Right now adding new documentation is a chore, assemble the file then
> modifying some obscure files to have monodoc show your work I think it
> coul be easier, many times I see in the lists how to make docs and how
> to install them in monodoc.
> 
> Hector
> 
> On Tue, 2004-10-26 at 00:56 -0400, Miguel de Icaza wrote:
> > Hello,
> > 
> > > 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.
> > 
> > Am pondering the patch, but only because the point of the monodoc.xml
> > file was that we would create a hierarchy that made sense, so people
> > should be encouraged to send their requests, as opposed to have every
> > application add just another menu entry everywhere.
> > 
> > Miguel
> > _______________________________________________
> > Mono-docs-list maillist  -  Mono-docs-list@lists.ximian.com
> > http://lists.ximian.com/mailman/listinfo/mono-docs-list
> 
> _______________________________________________
> Mono-docs-list maillist  -  Mono-docs-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-docs-list

--=_galadriel.fciencias.unam.mx-54994-1098781226-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. (hectorgm@ciencias.unam.mx)
//
// (C) 2004, Hector E. Gomez Morales
//
using System;
using System.IO;
using System.Xml;
using System.Reflection;

namespace MonoDoc
{
	public class Driver
	{
		static void Usage ()
		{
			Console.WriteLine ("Usage: mono installer.exe --add | --del");
			Console.WriteLine ("   --add <label> <package> [<parent>]");
			Console.WriteLine ("   --del <package>");
			Environment.Exit (1);
		}

		static void Main (string [] args)
		{
		 	bool alt_parent;
		 	string def_parent = "various";

			if (args.Length == 0 || args.Length == 1 || args.Length > 4)
				Usage();
			
			if (args.Length == 4)
				alt_parent = true;
			else
				alt_parent = false;

			Installer install = new Installer ();

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

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

	public class Installer
	{
		static string base_path;
		static string config;

		// Gets the monodoc dir where monodoc.xml and the sources directory are located.
		string GetDocPath () 
		{
			Assembly asm = Assembly.LoadWithPartialName ("monodoc");
			string cfg_file = asm.Location + ".config";

			XmlDocument doc = new XmlDocument ();
			try {
				doc.Load (cfg_file);
			} catch (FileNotFoundException e) {
				Console.WriteLine ("Error: No monodoc.dll.config found.");
				Console.WriteLine ("A reinstall of monodoc should correct this.");
				Environment.Exit (1);
			}

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

		// Meta method for the installation.
		public void Install (string label, string parent_name, string package_name)
		{
			XmlDocument doc = new XmlDocument ();
			doc = ReadConfig ();

			if (AlreadyInstalled (doc, package_name)) {
				Console.WriteLine ("Error: Previous install of " + package_name + " detected.");
				Environment.Exit (1);
			}

			CreateSource ("ecma", package_name);
			CopyDoc (package_name, base_path);
			CreateNode (doc, label, parent_name, package_name);
			WriteConfig (doc, config);

			Console.WriteLine ("Documentation install of " + package_name + " successful.");
		}

		// Creates the corresponding node in monodoc.xml for the documentation.
		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);
		}

		// Reads monodoc.xml and loads it to a XmlDocument for editing later.
		XmlDocument ReadConfig ()
		{
			base_path = GetDocPath ();
			config = base_path + "/monodoc.xml";

			XmlDocument document = new XmlDocument ();
			try {
				XmlTextReader reader = new XmlTextReader (config);
				document.Load (reader);
				reader.Close ();
			} catch (FileNotFoundException e) {
				Console.WriteLine ("Error: No monodoc.xml found.");
				Console.WriteLine ("Error: A reinstall of monodoc should fix this.");
				Environment.Exit (1);
			}
			
			return document;
		}

		// Writes modified monodoc.xml or foo.source file.
		void WriteConfig (XmlDocument doc, string filename)
		{
			try {
				XmlTextWriter writer = new XmlTextWriter (filename, null);
				writer.Formatting = Formatting.Indented;
				doc.WriteTo (writer);
				writer.WriteString ("\n");
				writer.Close ();
			} catch (UnauthorizedAccessException e) {
				Console.WriteLine ("Error: Root privileges needed to uninstall documentation.");
				Environment.Exit (1);
			}
		}

		// Creates the foo.source for foo package need for monodoc (to know which provider to use to visualize the docs).
		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");
		}

		// Copy all the needed files to the sources directory. 
		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 (Exception 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 files or higher privileges needed for installation.");
				Environment.Exit (1);
			}
		}

		// Meta method for the uninstallation of the documentation.
		public void Uninstall (string package_name)
		{
			XmlDocument doc = new XmlDocument ();
			doc = ReadConfig ();

			DeleteNode (doc, package_name);
			WriteConfig (doc, config);
			DeleteDoc (package_name, base_path);
			Console.WriteLine ("Documentation uninstall of " + package_name + " successful.");
		}

		// Deletes the corresponding node in monodoc.xml for the documentation.
		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);
			}
		}

		// Deletes the files from the package inside the sources directory.
		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");
			}
		}
		
		// Checks if a previous installation of foo package has ocurred.
		bool AlreadyInstalled (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-54994-1098781226-0001-2--