[Debtags-commits] [svn] r1579 - in tagcoll/trunk: . tagcoll tools

Enrico Zini enrico at costa.debian.org
Mon Feb 13 17:32:59 UTC 2006


Author: enrico
Date: Mon Feb 13 17:32:58 2006
New Revision: 1579

Modified:
   tagcoll/trunk/   (props changed)
   tagcoll/trunk/README
   tagcoll/trunk/tagcoll/BasicStringDiskIndex.cc
   tagcoll/trunk/tagcoll/BasicStringDiskIndex.h
   tagcoll/trunk/tagcoll/PatchCollection.cc
   tagcoll/trunk/tagcoll/PatchCollection.h
   tagcoll/trunk/tools/tagidx.cc
Log:
 r7310 at viaza:  enrico | 2006-02-13 18:26:33 +0100
 tagidx: implemented installing extra patches


Modified: tagcoll/trunk/README
==============================================================================
--- tagcoll/trunk/README	(original)
+++ tagcoll/trunk/README	Mon Feb 13 17:32:58 2006
@@ -173,6 +173,14 @@
 
 These are the TODO-list items currently being worked on::
 
+ - Make tagidx usable to power the central database on Alioth:
+    + mmap-based fast index
+    + patch directory
+    - 
+
+ - Create more IntIndex specific optimized methods instead of using the default
+   ones
+
  - Read http://people.lis.uiuc.edu/~twidale/irinterfaces/4othersystems.html
 
  - Replace ParserInputs with C++ isostreams

Modified: tagcoll/trunk/tagcoll/BasicStringDiskIndex.cc
==============================================================================
--- tagcoll/trunk/tagcoll/BasicStringDiskIndex.cc	(original)
+++ tagcoll/trunk/tagcoll/BasicStringDiskIndex.cc	Mon Feb 13 17:32:58 2006
@@ -36,7 +36,7 @@
 			  dir + "/pkgtags.idx", dir + "/tagpkgs.idx",
 			  pkgs, tags,
 			  pkgs, tags),
-	  pkgs(dir + "/pkgs.idx"), tags(dir + "/tags.idx")
+	  dir(dir), pkgs(dir + "/pkgs.idx"), tags(dir + "/tags.idx")
 {
 }
 

Modified: tagcoll/trunk/tagcoll/BasicStringDiskIndex.h
==============================================================================
--- tagcoll/trunk/tagcoll/BasicStringDiskIndex.h	(original)
+++ tagcoll/trunk/tagcoll/BasicStringDiskIndex.h	Mon Feb 13 17:32:58 2006
@@ -43,6 +43,7 @@
 class BasicStringDiskIndex : public IntDiskIndex<std::string, std::string>
 {
 protected:
+	std::string dir;
 	StringIndex pkgs;
 	StringIndex tags;
 
@@ -56,6 +57,8 @@
 	BasicStringDiskIndex(const std::string& dir);
 	virtual ~BasicStringDiskIndex() {}
 
+	const std::string& directory() const { return dir; }
+
 	static void remove(const std::string& dir);
 };
 

Modified: tagcoll/trunk/tagcoll/PatchCollection.cc
==============================================================================
--- tagcoll/trunk/tagcoll/PatchCollection.cc	(original)
+++ tagcoll/trunk/tagcoll/PatchCollection.cc	Mon Feb 13 17:32:58 2006
@@ -60,7 +60,6 @@
 	return changes.patch(item, coll.getTags(item));
 }
 
-
 template<class ITEM, class TAG>
 void PatchCollection<ITEM, TAG>::setChanges(const PatchList<ITEM, TAG>& changes)
 {
@@ -84,6 +83,16 @@
 }
 
 template<class ITEM, class TAG>
+void PatchCollection<ITEM, TAG>::addChanges(const PatchList<ITEM, TAG>& changes)
+{
+	PatchList<ITEM, TAG> ch(this->changes);
+
+	ch.addPatch(changes);
+
+	setChanges(ch);
+}
+
+template<class ITEM, class TAG>
 bool PatchCollection<ITEM, TAG>::hasTag(const TAG& tag) const
 {
 	OpSet<ITEM> items(coll.getItems(tag));

Modified: tagcoll/trunk/tagcoll/PatchCollection.h
==============================================================================
--- tagcoll/trunk/tagcoll/PatchCollection.h	(original)
+++ tagcoll/trunk/tagcoll/PatchCollection.h	Mon Feb 13 17:32:58 2006
@@ -47,7 +47,7 @@
 
 
 public:
-	PatchCollection(const Collection<ITEM, TAG>& coll) : coll(coll) {}
+	PatchCollection(const ReadonlyCollection<ITEM, TAG>& coll) : coll(coll) {}
 	virtual ~PatchCollection() {}
 
 	/**
@@ -56,10 +56,20 @@
 	const PatchList<ITEM, TAG>& getChanges() const { return changes; }
 
 	/**
+	 * Throw away all changes previously applied to this collection
+	 */
+	void resetChanges() { changes.clear(); }
+
+	/**
 	 * Set the changes list to a specific patch list
 	 */
 	void setChanges(const PatchList<ITEM, TAG>& changes);
 
+	/**
+	 * Add a specific patch list to the changes list
+	 */
+	void addChanges(const PatchList<ITEM, TAG>& changes);
+
     virtual bool hasTag(const TAG& tag) const;
 
 	virtual OpSet<ITEM> getTaggedItems() const;

Modified: tagcoll/trunk/tools/tagidx.cc
==============================================================================
--- tagcoll/trunk/tools/tagidx.cc	(original)
+++ tagcoll/trunk/tools/tagidx.cc	Mon Feb 13 17:32:58 2006
@@ -38,10 +38,14 @@
 #include <tagcoll/BasicStringDiskIndex.h>
 #include <tagcoll/ItemGrouper.h>
 #include <tagcoll/Consumer.h>
+#include <tagcoll/PatchCollection.h>
 
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <fcntl.h>
 #include <pwd.h>
+#include <dirent.h>
+#include <time.h>
 #include <errno.h>
 
 #include <tagcoll/StdioParserInput.h>
@@ -78,6 +82,31 @@
 using namespace std;
 using namespace Tagcoll;
 
+void mkpath(const std::string& dir)
+{
+	size_t sep = dir.rfind('/');
+
+	//cerr << "Ensuring existance of " << dir << endl;
+
+	// First ensure that the parent directory exists
+	if (sep != string::npos && sep != 0)
+		mkpath(dir.substr(0, sep));
+
+	// Then create this directory if needed
+	struct stat st;
+	if (stat(dir.c_str(), &st) == -1)
+	{
+		if (errno == ENOENT)
+		{
+			if (mkdir(dir.c_str(), 0777) == -1)
+				throw SystemException(errno, "creating directory " + dir);
+		} else
+			throw SystemException(errno, "getting informations about " + dir);
+	} else if (!S_ISDIR(st.st_mode))
+		throw ConsistencyCheckException("ensuring that " + dir + " is a directory");
+}
+
+
 #if 0
 void printItems(const set<string>& items, const string& prefix = "")
 {
@@ -137,6 +166,141 @@
 	}
 }
 
+PatchList<string, string> readPatchFromFile(const std::string& filename)
+{
+	TrivialConverter<string, string> conv;
+	StdioParserInput input(filename);
+	return TextFormat<string, string>::parsePatch(conv, conv, input);
+
+}
+
+/**
+ * Only read files that do not start with a '.' and are not regular files or
+ * symlinks
+ */
+PatchList<string, string> readPatchesFromDir(const std::string& dirname)
+{
+	PatchList<string, string> res;
+
+	DIR* dir = opendir(dirname.c_str());
+	if (dir == NULL)
+		throw SystemException(errno, "opening directory " + dirname);
+	
+	struct dirent* ent;
+	while ((ent = readdir(dir)) != NULL)
+	{
+		// Skip files starting with a dot
+		if (ent->d_name[0] == '.')
+			continue;
+
+		string file = dirname + "/" + ent->d_name;
+		struct stat st;
+		if (stat(file.c_str(), &st) == -1)
+			throw SystemException(errno, "getting informations about " + file);
+
+		// We only want regular files or symlinks
+		if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
+			continue;
+
+		res.addPatch(readPatchFromFile(file));
+	}
+	closedir(dir);
+
+	return res;
+}
+
+void removePatchesFromDir(const std::string& dirname)
+{
+	DIR* dir = opendir(dirname.c_str());
+	if (dir == NULL)
+		throw SystemException(errno, "opening directory " + dirname);
+	
+	struct dirent* ent;
+	while ((ent = readdir(dir)) != NULL)
+	{
+		// Skip files starting with a dot
+		if (ent->d_name[0] == '.')
+			continue;
+
+		string file = dirname + "/" + ent->d_name;
+		struct stat st;
+		if (stat(file.c_str(), &st) == -1)
+			throw SystemException(errno, "getting informations about " + file);
+
+		// We only want regular files or symlinks
+		if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)))
+			continue;
+
+		if (unlink(file.c_str()) == -1)
+			throw SystemException(errno, "removing file " + file);
+	}
+	closedir(dir);
+}
+
+class Index : public PatchCollection<std::string, std::string>
+{
+protected:
+	BasicStringDiskIndex ro_idx;
+
+public:
+	Index(const std::string& dir)
+		: PatchCollection<std::string, std::string>(ro_idx),
+			ro_idx(dir)
+	{
+		// Read the patches
+		setChanges(readPatchesFromDir(dir + "/patches"));
+	}
+
+	virtual ~Index() {}
+
+	void addPatch(const PatchList<std::string, std::string>& patch, const std::string& name, bool overwrite = false)
+	{
+		TrivialConverter<string, string> conv;
+		string patchfile = ro_idx.directory() + "/patches/" + name;
+		
+		int fd = open(patchfile.c_str(), O_CREAT | O_WRONLY | (overwrite ? O_TRUNC : O_EXCL), 0666);
+		if (fd == -1)
+			throw SystemException(errno, "creating file " + patchfile);
+
+		FILE* out = fdopen(fd, "w");
+		if (out == NULL)
+			throw SystemException(errno, "fdopening file " + patchfile);
+
+		TextFormat<string, string>::outputPatch(conv, conv, patch, out);
+		fclose(out);
+
+		addChanges(patch);
+	}
+
+	static void remove(const std::string& dir)
+	{
+		string patchdir = dir + "/patches";
+		removePatchesFromDir(patchdir);
+
+		if (rmdir(patchdir.c_str()) == -1)
+			if (errno == ENOTEMPTY)
+				cerr << "Directory " + patchdir + " was not empty: skipping removing it";
+			else
+				throw SystemException(errno, "Removing directory " + patchdir);
+
+		BasicStringDiskIndex::remove(dir);
+	}
+};
+
+class Indexer : public BasicStringDiskIndexer
+{
+public:
+	virtual ~Indexer() {}
+
+	void write(const std::string& dir)
+	{
+		BasicStringDiskIndexer::write(dir);
+
+		// Create the patches directory if it does not exist yet
+		mkpath(dir + "/patches");
+	}
+};
+
 #if 0
 PatchList<string, string> readPatches(const string& file)
 	throw (FileException, ParserException)
@@ -355,7 +519,7 @@
 	}
 };
 
-enum valid_command { CREATE, REMOVE, CAT /*, DIFF, RELATED, IMPLICATIONS, HIERARCHY, CLEANHIERARCHY, REVERSE, FINDSPECIALS, GREP, ITEMS */ };
+enum valid_command { CREATE, REMOVE, ADDPATCH, CAT /*, DIFF, RELATED, IMPLICATIONS, HIERARCHY, CLEANHIERARCHY, REVERSE, FINDSPECIALS, GREP, ITEMS */ };
 
 #if 0
 class Reader
@@ -477,6 +641,15 @@
 	}
 }
 
+string get_username()
+{
+	struct passwd* pw = getpwuid(getuid());
+	if (pw != NULL)
+		return pw->pw_name;
+	else
+		return string();
+}
+
 string indexdir(CommandlineParserWithCommand& opts)
 {
 	if (opts.get("index").defined())
@@ -489,30 +662,6 @@
 	throw NotFoundException("looking for a suitable place for the index directory (tried the --index commandline option, the $TAGIDX environment variable and the home directory)");
 }
 
-void mkpath(const std::string& dir)
-{
-	size_t sep = dir.rfind('/');
-
-	//cerr << "Ensuring existance of " << dir << endl;
-
-	// First ensure that the parent directory exists
-	if (sep != string::npos && sep != 0)
-		mkpath(dir.substr(0, sep));
-
-	// Then create this directory if needed
-	struct stat st;
-	if (stat(dir.c_str(), &st) == -1)
-	{
-		if (errno == ENOENT)
-		{
-			if (mkdir(dir.c_str(), 0777) == -1)
-				throw SystemException(errno, "creating directory " + dir);
-		} else
-			throw SystemException(errno, "getting informations about " + dir);
-	} else if (!S_ISDIR(st.st_mode))
-		throw ConsistencyCheckException("ensuring that " + dir + " is a directory");
-}
-
 int main(int argc, const char* argv[])
 {
 	try {
@@ -521,6 +670,8 @@
 				"Commands are:\n"
 				"  create       create the index from a tagged collection\n"
 				"  remove       deletes the disk index\n"
+				"  addpatch [file1 [file2 [...]]]\n"
+				"               installs the given files as patches to the collection\n"
 				"  cat          output the collection\n"
 /*
 				"  reverse      \"reverse\" the collection, outputting one with items\n"
@@ -548,6 +699,7 @@
 		opts.add("index", 'I', "index", "directory where the index files are stored", "dir");
 		opts.add("groupitems", 'g', "group-items", "group items with the same tagset in the output collection");
 		opts.add("quiet", 'q', "quiet", "produce no output");
+		opts.add("force", 'f', "force", "force overwrite");
 #if 0
 		opts.add("derived", 'e', "derived-tags-from", "use an external list of derived tags", "file");
 		opts.add("extimpl", 'i', "implications-from", "use an external list of implications", "file");
@@ -569,6 +721,7 @@
 		opts.addCommand("create", (int)CREATE);
 		opts.addCommand("cat", (int)CAT);
 		opts.addCommand("remove", (int)REMOVE);
+		opts.addCommand("addpatch", (int)ADDPATCH);
 #if 0
 		opts.addCommand("copy", (int)COPY);
 		opts.addCommand("reverse", (int)REVERSE);
@@ -599,7 +752,7 @@
 				string dir = indexdir(opts);
 				mkpath(dir);
 
-				BasicStringDiskIndexer indexer;
+				Indexer indexer;
 				
 				if (args.hasNext())
 					while (args.hasNext())
@@ -611,16 +764,54 @@
 
 				break;
 			}
+			case ADDPATCH:
+			{
+				string dir = indexdir(opts);
+				Index idx(dir);
+
+				if (args.hasNext())
+				{
+					while (args.hasNext())
+					{
+						string filename = args.next();
+						size_t pos = filename.rfind('/');
+						string name = pos == string::npos ? filename : filename.substr(pos + 1);
+
+						PatchList<string, string> patch = readPatchFromFile(filename);
+						if (patch.size() > 0)
+						{
+							idx.addPatch(patch, name, opts.get("force").defined());
+						} else {
+							cerr << "skipped empty patch file " << filename << endl;
+						}
+					}
+				} else {
+					TrivialConverter<string, string> conv;
+					StdioParserInput input(stdin, "(stdin)");
+					PatchList<string, string> patch = TextFormat<string, string>::parsePatch(conv, conv, input);
+					// Compute a default name from username and current time
+					char name[50];
+					time_t t = time(NULL);
+					strftime(name, 50, "%Y%m%d-%H%M%S", localtime(&t));
+					if (patch.size() > 0)
+					{
+						idx.addPatch(patch, get_username() + "-" + name, opts.get("force").defined());
+					} else
+						cerr << "not adding empty patch" << endl;
+				}
+
+				break;
+			}
 			case REMOVE:
 			{
 				string dir = indexdir(opts);
-				BasicStringDiskIndex::remove(dir);
+				Index::remove(dir);
 				break;
 			}
 			case CAT:
 			{
 				string dir = indexdir(opts);
-				BasicStringDiskIndex idx(dir);
+				Index idx(dir);
 
 				output(opts, idx);
 				break;



More information about the Debtags-commits mailing list