[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