[PATCH] Searching in log

Mirek Jezbera <[email protected]> Sat, 29 Dec 2012 09:21:46 +0100
Newsgroups gmane.comp.version-control.subversion.rapidsvn.devel
Message-ID <20121229082146.GA20771@titan>
------=_Part_777_1699845876.1356770011945
Content-Type: multipart/mixed; 
	boundary="----=_Part_778_1334681891.1356770011945"
Content-Disposition: inline

------=_Part_778_1334681891.1356770011945
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Hello,
I have implemented searching in log. You can search in comments, affected f=
iles
or by author. It is implemented using SQLite to index data from repository.
For rapidsvn repository with 8263 revisions it tooks about 25 seconds to
reindex and index file has 2 MB. Because index file is stored in same place=
 as
config file, I have implemented migration code to move config file ~/.Rapid=
SVN
to ~/.RapidSVN/config.ini.
Searching is IMHO quite fast. I have two TODOs in log_dlg.cpp - I don't kno=
w how
to log errors from log dialog.
Users without SQLite should compile rapidsvn, but this functionality will b=
e
hidden.
Feel free to comment the code.

--=20
Jezz
mail:   [email protected]
jabber: [email protected]

------=_Part_778_1334681891.1356770011945
Content-Type: text/x-diff; charset=us-ascii; 
	name=04_typedef_for_changed_paths.diff
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=04_typedef_for_changed_paths.diff

Index: libsvncpp/include/svncpp/log_entry.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- libsvncpp/include/svncpp/log_entry.hpp=09(revision 2)
+++ libsvncpp/include/svncpp/log_entry.hpp=09(working copy)
@@ -54,7 +54,6 @@
=20
   struct LogEntry
   {
-public:
     LogEntry();
=20
     LogEntry(const svn_revnum_t revision,
@@ -65,7 +64,8 @@
     svn_revnum_t revision;
     std::string author;
     std::string message;
-    std::list<LogChangePathEntry> changedPaths;
+    typedef std::list<LogChangePathEntry> ChangePathCollection;
+    ChangePathCollection changedPaths;
     apr_time_t date;
   };
 }
Index: librapidsvn/src/log_dlg.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/log_dlg.cpp=09(revision 7)
+++ librapidsvn/src/log_dlg.cpp=09(working copy)
@@ -234,7 +234,7 @@
=20
   wxASSERT(focusedFileIdx !=3D -1);
=20
-  std::list<svn::LogChangePathEntry>::const_iterator it =3D affectedFiles.=
begin();
+  svn::LogEntry::ChangePathCollection::const_iterator it =3D affectedFiles=
.begin();
   std::advance(it, focusedFileIdx);
   wxString file(Utf8ToLocal(m->repositoryPath.getRepositoryRoot() + it->pa=
th));
=20
@@ -399,12 +399,12 @@
   return affectedPaths;
 }
=20
-std::list<svn::LogChangePathEntry>
-LogDlg::FilterAffectedPaths(std::list<svn::LogChangePathEntry> const & cha=
ngedPaths, std::set<std::string> const & filter)
+svn::LogEntry::ChangePathCollection
+LogDlg::FilterAffectedPaths(svn::LogEntry::ChangePathCollection const & ch=
angedPaths, std::set<std::string> const & filter)
 {
-  std::list<svn::LogChangePathEntry> result;
+  svn::LogEntry::ChangePathCollection result;
=20
-  for (std::list<svn::LogChangePathEntry>::const_iterator it =3D changedPa=
ths.begin();
+  for (svn::LogEntry::ChangePathCollection::const_iterator it =3D changedP=
aths.begin();
       it !=3D changedPaths.end();
       ++it)
   {
@@ -428,7 +428,7 @@
   std::set<std::string> result;
   const svn::LogEntry & entry =3D (*m->entries)[itemIndex];
=20
-  for (std::list<svn::LogChangePathEntry>::const_iterator it =3D entry.cha=
ngedPaths.begin();
+  for (svn::LogEntry::ChangePathCollection::const_iterator it =3D entry.ch=
angedPaths.begin();
       it !=3D entry.changedPaths.end();
       ++it)
   {
Index: librapidsvn/include/log_dlg.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/log_dlg.hpp=09(revision 6)
+++ librapidsvn/include/log_dlg.hpp=09(working copy)
@@ -89,7 +89,7 @@
   struct Data;
   std::auto_ptr<Data> m;
  =20
-  std::list<svn::LogChangePathEntry> affectedFiles;
+  svn::LogEntry::ChangePathCollection affectedFiles;
=20
   void OnAffectedFileOrDirCommand(wxCommandEvent & event);
=20
@@ -103,7 +103,7 @@
   void ReduceSelectionToOnlyTwoItems();
   void FillAffectedFiles();
   std::set<std::string> GetIntersectionOfAffectedPaths();
-  std::list<svn::LogChangePathEntry> FilterAffectedPaths(std::list<svn::Lo=
gChangePathEntry> const & changedPaths, std::set<std::string> const & filte=
r);
+  svn::LogEntry::ChangePathCollection FilterAffectedPaths(svn::LogEntry::C=
hangePathCollection const & changedPaths, std::set<std::string> const & fil=
ter);
   std::set<std::string> GetAffectedPathsForItem(long itemIndex);
 };
=20
Index: librapidsvn/include/log_aff_list.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/log_aff_list.hpp=09(revision 3)
+++ librapidsvn/include/log_aff_list.hpp=09(working copy)
@@ -68,7 +68,7 @@
     wxListCtrl::DeleteAllItems();
   }
=20
-  void SetValue(const std::list<svn::LogChangePathEntry> & changedPaths)
+  void SetValue(const svn::LogEntry::ChangePathCollection & changedPaths)
   {
     Freeze();
=20
@@ -79,7 +79,7 @@
       char actionBuffer [2];
       actionBuffer [1] =3D 0;
=20
-      std::list<svn::LogChangePathEntry>::const_iterator it;
+      svn::LogEntry::ChangePathCollection::const_iterator it;
=20
       for (it=3DchangedPaths.begin(); it!=3DchangedPaths.end(); it++)
       {

------=_Part_778_1334681891.1356770011945
Content-Type: text/x-diff; charset=us-ascii; name=05_sqlite_searching.diff
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename=05_sqlite_searching.diff

Index: configure.in
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- configure.in=09(revision 2)
+++ configure.in=09(working copy)
@@ -225,6 +225,13 @@
 fi
=20
 dnl
+dnl SQLite
+dnl
+AC_CHECK_HEADERS([sqlite3.h], ,)
+AC_CHECK_LIB([sqlite3], [sqlite3_libversion_number], [LIBSQLITE=3D-lsqlite=
3], ,)
+AC_SUBST(LIBSQLITE)
+
+dnl
 dnl XsltProc
 dnl=20
 XSLTPROC=3Dxsltproc
Index: librapidsvn/src/repository_searcher_builder.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/repository_searcher_builder.cpp=09(revision 0)
+++ librapidsvn/src/repository_searcher_builder.cpp=09(revision 0)
@@ -0,0 +1,83 @@
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ * Copyright (c) 2002-2012 The RapidSVN Group.  All rights reserved.
+ *
+ * This program 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.
+ *
+ * This program 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 this program (in the file GPL.txt.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://rapidsvn.tigris.org/.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ */
+
+// stl
+#include <memory>
+
+// rapidsvn
+#include "repository_searcher_iface.hpp"
+#if HAVE_SQLITE3_H
+# include "repository_searcher.hpp"
+#endif
+#include "repository_searcher_builder.hpp"
+
+std::string RepositorySearcherBuilder::m_dataDirectory;
+
+void
+RepositorySearcherBuilder::setUserDataDirectoryWithEndingSeparator(std::st=
ring const & directory)
+{
+  m_dataDirectory =3D directory;
+}
+
+RepositorySearcherBuilder &
+RepositorySearcherBuilder::getInstance()
+{
+  static RepositorySearcherBuilder instance;
+  return instance;
+}
+
+RepositorySearcherBuilder::~RepositorySearcherBuilder()
+{
+  for (std::map<std::string, RepositorySearcherIface *>::const_iterator it=
 =3D m_searchers.begin();
+      it !=3D m_searchers.end();
+      ++it)
+  {
+    delete it->second;
+  }
+}
+
+RepositorySearcherIface *
+RepositorySearcherBuilder::getOrCreateSearcher(svn::Context * context, std=
::string const & repositoryPath)
+{
+  std::map<std::string, RepositorySearcherIface *>::const_iterator it;
+  it =3D m_searchers.find(repositoryPath);
+  if (it !=3D m_searchers.end())
+    return it->second;
+#if HAVE_SQLITE3_H
+  std::auto_ptr<RepositorySearcher> searcher(new RepositorySearcher(contex=
t, repositoryPath));
+  searcher->openDatabase(m_dataDirectory);
+  searcher->createTablesIfNotExist();
+  m_searchers[repositoryPath] =3D searcher.release();
+  return m_searchers[repositoryPath];
+#else
+  // Only SQLite implementation available
+  return NULL;
+#endif
+}
+
+/* -----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../rapidsvn-dev.el")
+ * end:
+ */
Index: librapidsvn/src/log_dlg.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/log_dlg.cpp=09(revision 8)
+++ librapidsvn/src/log_dlg.cpp=09(working copy)
@@ -45,37 +45,107 @@
 #include "log_aff_list.hpp"
 #include "log_rev_list.hpp"
 #include "merge_dlg.hpp"
+#include "res/bitmaps/filteredit.png.h"
+#include "res/bitmaps/refresh.png.h"
 #include "utils.hpp"
 #include "annotate_data.hpp"
=20
+namespace
+{
+  template<typename T>
+  struct PointerReference
+  {
+    PointerReference(T & reference) : m_reference(&reference) {}
+
+    PointerReference(PointerReference<T> const & reference) : m_reference(=
reference.m_reference) {}
+
+    operator T & () { return *m_reference; }
+
+    T * m_reference;
+  };
+
+  class FilteredLogEntries
+  {
+  public:
+    typedef std::vector<PointerReference<const svn::LogEntry> > LogEntryRe=
ferenceVector;
+
+    FilteredLogEntries(const svn::LogEntries * entries)
+      : m_entries(entries)
+    {
+      m_visibleEntries.reserve(m_entries->size());
+      showAllEntries();
+    }
+
+    LogEntryReferenceVector::iterator begin()
+    {
+      return m_visibleEntries.begin();
+    }
+
+    LogEntryReferenceVector::iterator end()
+    {
+      return m_visibleEntries.end();
+    }
+
+    void setVisibleRevisions(std::set<svn_revnum_t> const & visibleRevisio=
ns)
+    {
+      m_visibleEntries.clear();
+      for (svn::LogEntries::const_iterator it =3D m_entries->begin(); it !=
=3D m_entries->end(); ++it)
+      {
+        if (visibleRevisions.find(it->revision) !=3D visibleRevisions.end(=
))
+          m_visibleEntries.push_back(*it);
+      }
+    }
+
+    void showAllEntries()
+    {
+      m_visibleEntries.clear();
+      for (svn::LogEntries::const_iterator it =3D m_entries->begin(); it !=
=3D m_entries->end(); ++it)
+      {
+        m_visibleEntries.push_back(*it);
+      }
+    }
+
+    svn::LogEntry const & operator[](int idx)
+    {
+      return m_visibleEntries[idx];
+    }
+
+  private:
+    const svn::LogEntries * m_entries;
+    LogEntryReferenceVector m_visibleEntries;
+  };
+}
+
 struct LogDlg::Data
 {
 public:
-  const svn::LogEntries * entries;
+  FilteredLogEntries entries;
   wxString path;
   svn::RepositoryPath repositoryPath;=20
+  RepositorySearcherIface *searcher;
=20
 public:
   Data(const svn::RepositoryPath & path_,
-       const svn::LogEntries * entries_)
-      : entries(entries_), path(Utf8ToLocal(path_.c_str())), repositoryPat=
h(path_)
+       const svn::LogEntries * entries_,
+       RepositorySearcherIface * searcher_)
+      : entries(entries_), path(Utf8ToLocal(path_.c_str())), repositoryPat=
h(path_), searcher(searcher_)
   {
   }
-
 };
=20
 LogDlg::LogDlg(wxWindow * parent,
                const svn::RepositoryPath & path,=20
-               const svn::LogEntries * entries)
+               const svn::LogEntries * entries,
+               RepositorySearcherIface *searcher)
     : LogDlgBase(parent, -1, _("Log History"), wxDefaultPosition,
                  wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER |=
 wxMAXIMIZE_BOX)
 {
-  m =3D std::auto_ptr<Data>(new Data(path, entries));
+  m =3D std::auto_ptr<Data>(new Data(path, entries, searcher));
=20
-  m_staticRevisions->SetLabel(
-    wxString::Format(_("History: %d revisions"), entries->size()));
+  if (searcher =3D=3D NULL)
+    m_upperLeftSizer->Hide(m_searchSizer);
=20
-  m_listRevisions->SetEntries(entries);
+  UpdateRevisionsList();
=20
   CheckControls();
=20
@@ -85,6 +155,9 @@
   m_mainSizer->SetSizeHints(this);
   m_mainSizer->Fit(this);
=20
+  m_buttonSearch->SetBitmapLabel(EMBEDDED_BITMAP(filteredit_png));
+  m_buttonReindex->SetBitmapLabel(EMBEDDED_BITMAP(refresh_png));
+
   m_listFiles->Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(=
LogDlg::OnAffectedFileOrDirCommand), NULL, this);
=20
   CentreOnParent();
@@ -271,7 +344,7 @@
   else
   {
     long itemIndex =3D m_listRevisions->GetFirstSelected();
-    const svn::LogEntry & entry =3D (*m->entries)[itemIndex];
+    const svn::LogEntry & entry =3D m->entries[itemIndex];
=20
     wxString message(Utf8ToLocal(entry.message.c_str()));
     message.Trim();
@@ -283,6 +356,17 @@
 }
=20
 void
+LogDlg::UpdateRevisionsList()
+{
+  m_listRevisions->SetEntries(m->entries.begin(), m->entries.end());
+
+  m_staticRevisions->SetLabel(
+    wxString::Format(_("History: %d revisions"), m_listRevisions->GetItemC=
ount()));
+
+  UpdateSelection();
+}
+
+void
 LogDlg::OnRevSelected(wxListEvent & WXUNUSED(event))
 {
   UpdateSelection();
@@ -295,8 +379,49 @@
   UpdateSelection();
 }
=20
+void
+LogDlg::OnSearch(wxCommandEvent & WXUNUSED(event))
+{
+  if (m->searcher =3D=3D NULL)
+    return;
=20
+  try
+  {
+    if (m_textSearch->IsEmpty())
+    {
+      m->entries.showAllEntries();
+    }
+    else
+    {
+      std::set<svn_revnum_t> found =3D m->searcher->search(
+          LocalToUtf8(m_textSearch->GetValue()),
+          (RepositorySearcherIface::SearchType)m_searchType->GetCurrentSel=
ection());
+      m->entries.setVisibleRevisions(found);
+    }
+
+    UpdateRevisionsList();
+  }
+  catch (SearcherException const &)
+  {
+    // TODO: LOG ERROR
+  }
+}
+
 void
+LogDlg::OnReindex(wxCommandEvent & WXUNUSED(event))
+{
+  try
+  {
+    if (m->searcher !=3D NULL)
+      m->searcher->reindex();
+  }
+  catch (SearcherException const &)
+  {
+    // TODO: LOG ERROR
+  }
+}
+
+void
 LogDlg::CheckControls()
 {
   svn::Path pathUtf8(PathUtf8(m->path));
@@ -364,7 +489,7 @@
     return;
   }
=20
-  const svn::LogEntry & entry =3D (*m->entries)[firstSelectedItemIndex];
+  const svn::LogEntry & entry =3D m->entries[firstSelectedItemIndex];
   affectedFiles =3D entry.changedPaths;
=20
   if (m_listRevisions->GetSelectedItemCount() > 1)
@@ -426,7 +551,7 @@
   }
=20
   std::set<std::string> result;
-  const svn::LogEntry & entry =3D (*m->entries)[itemIndex];
+  const svn::LogEntry & entry =3D m->entries[itemIndex];
=20
   for (svn::LogEntry::ChangePathCollection::const_iterator it =3D entry.ch=
angedPaths.begin();
       it !=3D entry.changedPaths.end();
Index: librapidsvn/src/rapidsvn_config.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/rapidsvn_config.cpp=09(revision 0)
+++ librapidsvn/src/rapidsvn_config.cpp=09(revision 0)
@@ -0,0 +1,100 @@
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ * Copyright (c) 2002-2012 The RapidSVN Group.  All rights reserved.
+ *
+ * This program 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.
+ *
+ * This program 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 this program (in the file GPL.txt.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://rapidsvn.tigris.org/.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ */
+// wxWidgets
+#include "wx/wx.h"
+#include "wx/dir.h"
+#include "wx/file.h"
+#include "wx/fileconf.h"
+#include "wx/stdpaths.h"
+
+// app
+#include "repository_searcher_builder.hpp"
+#include "rapidsvn_config.hpp"
+#include "version.hpp"
+#include "utils.hpp"
+
+#define APP_CONFIG wxT("config.ini")
+#define CACHE_DIR  wxT("cache")
+
+Config::Config()
+{
+  Init();
+}
+
+wxConfigBase *
+Config::GetConfig()
+{
+  return wxConfigBase::Get();
+}
+
+void
+Config::Init()
+{
+  m_userDataDir =3D wxStandardPaths::Get().GetUserDataDir();
+  m_cacheDir =3D m_userDataDir + wxT("/") + CACHE_DIR;
+
+  CreateDataDirectoryIfMissing();
+#ifndef _WIN32
+  wxString configFileName =3D m_userDataDir + wxT("/") + APP_CONFIG;
+  wxConfigBase::Set(new wxFileConfig(APPLICATION_NAME, APPLICATION_NAME, c=
onfigFileName));
+#endif
+
+  RepositorySearcherBuilder::setUserDataDirectoryWithEndingSeparator(Local=
ToUtf8(m_cacheDir + wxT("/")));
+}
+
+void
+Config::CreateDataDirectoryIfMissing()
+{
+  if (!wxDir::Exists(m_userDataDir))
+  {
+    if (wxFile::Exists(m_userDataDir))
+    {
+      MigrateOldConfiguration();
+    }
+    else
+    {
+      wxMkdir(m_userDataDir);
+    }
+  }
+  if (!wxDir::Exists(m_cacheDir))
+  {
+    wxMkdir(m_cacheDir);
+  }
+}
+
+void
+Config::MigrateOldConfiguration()
+{
+  wxString configFileName =3D m_userDataDir + wxT("/") + APP_CONFIG;
+
+  wxRenameFile(m_userDataDir, m_userDataDir + wxT(".bak"));
+  wxMkdir(m_userDataDir);
+  wxRenameFile(m_userDataDir + wxT(".bak"), configFileName);
+}
+
+/* -----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../rapidsvn-dev.el")
+ * end:
+ */
Index: librapidsvn/src/main_frame.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/main_frame.cpp=09(revision 5)
+++ librapidsvn/src/main_frame.cpp=09(working copy)
@@ -42,6 +42,7 @@
=20
 // app
 #include "rapidsvn_app.hpp"
+#include "rapidsvn_config.hpp"
 #include "columns.hpp"
 #include "config.hpp"
 #include "destination_dlg.hpp"
@@ -664,7 +665,8 @@
   // Retrieve a pointer to the application configuration object.
   // If the object is not created, it will be created upon the first
   // call to Get().
-  wxConfigBase *cfg =3D wxConfigBase::Get();
+  Config rapidSvnConfig;
+  wxConfigBase *cfg =3D rapidSvnConfig.GetConfig();
=20
   // Now set icons for the application
   // (several sizes are available OS/windowing system
@@ -1887,7 +1889,7 @@
=20
     if (pData !=3D 0)
     {
-      LogDlg dlg(this, pData->target, pData->logEntries);
+      LogDlg dlg(this, pData->target, pData->logEntries, pData->searcher);
       dlg.ShowModal();
=20
       delete pData->logEntries;
Index: librapidsvn/src/rapidsvn_generated.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/rapidsvn_generated.cpp=09(revision 5)
+++ librapidsvn/src/rapidsvn_generated.cpp=09(working copy)
@@ -1152,17 +1152,39 @@
 =09wxBoxSizer* upperSizer;
 =09upperSizer =3D new wxBoxSizer( wxHORIZONTAL );
 =09
-=09wxBoxSizer* upperLeftSizer;
-=09upperLeftSizer =3D new wxBoxSizer( wxVERTICAL );
+=09m_upperLeftSizer =3D new wxBoxSizer( wxVERTICAL );
 =09
+=09m_searchSizer =3D new wxBoxSizer( wxHORIZONTAL );
+=09
+=09m_staticSearch =3D new wxStaticText( m_upperPanel, wxID_ANY, _("Search"=
), wxDefaultPosition, wxDefaultSize, 0 );
+=09m_staticSearch->Wrap( -1 );
+=09m_searchSizer->Add( m_staticSearch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5=
 );
+=09
+=09m_textSearch =3D new wxTextCtrl( m_upperPanel, wxID_ANY, wxEmptyString,=
 wxDefaultPosition, wxDefaultSize, 0 );
+=09m_searchSizer->Add( m_textSearch, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5 )=
;
+=09
+=09wxString m_searchTypeChoices[] =3D { _("author"), _("comment"), _("path=
") };
+=09int m_searchTypeNChoices =3D sizeof( m_searchTypeChoices ) / sizeof( wx=
String );
+=09m_searchType =3D new wxChoice( m_upperPanel, wxID_ANY, wxDefaultPositio=
n, wxDefaultSize, m_searchTypeNChoices, m_searchTypeChoices, 0 );
+=09m_searchType->SetSelection( 2 );
+=09m_searchSizer->Add( m_searchType, 0, wxALL, 5 );
+=09
+=09m_buttonSearch =3D new wxBitmapButton( m_upperPanel, wxID_ANY, wxNullBi=
tmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
+=09m_searchSizer->Add( m_buttonSearch, 0, wxALIGN_CENTER_VERTICAL|wxALL, 1=
 );
+=09
+=09m_buttonReindex =3D new wxBitmapButton( m_upperPanel, wxID_ANY, wxNullB=
itmap, wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW );
+=09m_searchSizer->Add( m_buttonReindex, 0, wxALIGN_CENTER_VERTICAL|wxALL, =
1 );
+=09
+=09m_upperLeftSizer->Add( m_searchSizer, 0, wxEXPAND, 5 );
+=09
 =09m_staticRevisions =3D new wxStaticText( m_upperPanel, wxID_ANY, _("Hist=
ory: %d revisions"), wxDefaultPosition, wxDefaultSize, 0 );
 =09m_staticRevisions->Wrap( -1 );
-=09upperLeftSizer->Add( m_staticRevisions, 0, wxALL, 5 );
+=09m_upperLeftSizer->Add( m_staticRevisions, 0, wxALL, 5 );
 =09
 =09m_listRevisions =3D new LogRevList( m_upperPanel, wxID_ANY, wxDefaultPo=
sition, wxSize( 365,150 ), wxLC_REPORT );
-=09upperLeftSizer->Add( m_listRevisions, 1, wxALL|wxEXPAND, 5 );
+=09m_upperLeftSizer->Add( m_listRevisions, 1, wxALL|wxEXPAND, 5 );
 =09
-=09upperSizer->Add( upperLeftSizer, 1, wxEXPAND, 5 );
+=09upperSizer->Add( m_upperLeftSizer, 1, wxEXPAND, 5 );
 =09
 =09wxBoxSizer* upperRightSizer;
 =09upperRightSizer =3D new wxBoxSizer( wxVERTICAL );
@@ -1230,6 +1252,9 @@
 =09this->Layout();
 =09
 =09// Connect Events
+=09m_textSearch->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(=
 LogDlgBase::OnSearchEnter ), NULL, this );
+=09m_buttonSearch->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHa=
ndler( LogDlgBase::OnSearch ), NULL, this );
+=09m_buttonReindex->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventH=
andler( LogDlgBase::OnReindex ), NULL, this );
 =09m_listRevisions->Connect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxListEve=
ntHandler( LogDlgBase::OnRevDeselected ), NULL, this );
 =09m_listRevisions->Connect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEvent=
Handler( LogDlgBase::OnRevSelected ), NULL, this );
 =09m_buttonView->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHand=
ler( LogDlgBase::OnView ), NULL, this );
@@ -1243,6 +1268,9 @@
 LogDlgBase::~LogDlgBase()
 {
 =09// Disconnect Events
+=09m_textSearch->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandl=
er( LogDlgBase::OnSearchEnter ), NULL, this );
+=09m_buttonSearch->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEven=
tHandler( LogDlgBase::OnSearch ), NULL, this );
+=09m_buttonReindex->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEve=
ntHandler( LogDlgBase::OnReindex ), NULL, this );
 =09m_listRevisions->Disconnect( wxEVT_COMMAND_LIST_ITEM_DESELECTED, wxList=
EventHandler( LogDlgBase::OnRevDeselected ), NULL, this );
 =09m_listRevisions->Disconnect( wxEVT_COMMAND_LIST_ITEM_SELECTED, wxListEv=
entHandler( LogDlgBase::OnRevSelected ), NULL, this );
 =09m_buttonView->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventH=
andler( LogDlgBase::OnView ), NULL, this );
Index: librapidsvn/src/res/bitmaps/filteredit.png
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
Cannot display: file marked as a binary type.
svn:mime-type =3D application/octet-stream

Property changes on: librapidsvn/src/res/bitmaps/filteredit.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: librapidsvn/src/res/bitmaps/filteredit.png.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/res/bitmaps/filteredit.png.h=09(revision 0)
+++ librapidsvn/src/res/bitmaps/filteredit.png.h=09(revision 0)
@@ -0,0 +1,89 @@
+/* filteredit.png - 684 bytes */
+static const unsigned char filteredit_png[] =3D {
+  0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A,
+  0x00, 0x00, 0x00, 0x0D, 0x49, 0x48, 0x44, 0x52,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,
+  0x08, 0x03, 0x00, 0x00, 0x00, 0x28, 0x2D, 0x0F,
+  0x53, 0x00, 0x00, 0x01, 0x77, 0x50, 0x4C, 0x54,
+  0x45, 0xED, 0xED, 0xF3, 0xCD, 0xCE, 0xD6, 0xB5,
+  0xB5, 0xC0, 0xA7, 0xA8, 0xB5, 0xB8, 0xB9, 0xC7,
+  0xCB, 0xCC, 0xD7, 0xB7, 0xB8, 0xCD, 0xB4, 0xB6,
+  0xD8, 0xB9, 0xBC, 0xE7, 0xBF, 0xC2, 0xEB, 0xBB,
+  0xBE, 0xE3, 0xB3, 0xB6, 0xD8, 0xA8, 0xA9, 0xBB,
+  0xF0, 0xF0, 0xF4, 0xB9, 0xBA, 0xCF, 0xB7, 0xB9,
+  0xE0, 0xC6, 0xC9, 0xF2, 0xC9, 0xCC, 0xF5, 0xCB,
+  0xCE, 0xF5, 0xC5, 0xC8, 0xF1, 0xB1, 0xB4, 0xE1,
+  0xAB, 0xAC, 0xB8, 0xEE, 0xEE, 0xF0, 0xCC, 0xCD,
+  0xD3, 0xAB, 0xAF, 0xD4, 0xC7, 0xCA, 0xF3, 0xCA,
+  0xCD, 0xF6, 0xCB, 0xCE, 0xF7, 0xCC, 0xCF, 0xF6,
+  0xC7, 0xCA, 0xF1, 0xA3, 0xA5, 0xD4, 0xC0, 0xC1,
+  0xC9, 0xB4, 0xB4, 0xBE, 0xBB, 0xBE, 0xE7, 0xCD,
+  0xD0, 0xF7, 0xD0, 0xD3, 0xF8, 0xD4, 0xD7, 0xF8,
+  0xD5, 0xD7, 0xF7, 0xD2, 0xD5, 0xF8, 0xAD, 0xAE,
+  0xB9, 0xA6, 0xA7, 0xB4, 0xC4, 0xC7, 0xEE, 0xD2,
+  0xD4, 0xF8, 0xDA, 0xDC, 0xF8, 0xE6, 0xE7, 0xFA,
+  0xDD, 0xDF, 0xF9, 0xD0, 0xD2, 0xF6, 0x8E, 0x90,
+  0xA0, 0xA0, 0xA1, 0xAE, 0xCB, 0xCD, 0xF5, 0xE2,
+  0xE4, 0xFA, 0xF4, 0xF4, 0xFC, 0xF4, 0xF5, 0xFC,
+  0xE4, 0xE6, 0xFA, 0xD4, 0xD6, 0xF6, 0xBA, 0xBD,
+  0xE6, 0x95, 0x96, 0xA5, 0xBF, 0xBF, 0xC7, 0xA9,
+  0xAB, 0xD4, 0xC8, 0xCB, 0xF2, 0xD0, 0xD3, 0xF6,
+  0xDF, 0xE0, 0xF9, 0xED, 0xEE, 0xFB, 0xE2, 0xE3,
+  0xF8, 0xD0, 0xD1, 0xF4, 0xA6, 0xA9, 0xD5, 0xB7,
+  0xB7, 0xC1, 0xEE, 0xDF, 0xDA, 0xB4, 0x6D, 0x54,
+  0x82, 0x84, 0x97, 0xC9, 0xCC, 0xF3, 0xD4, 0xD7,
+  0xF6, 0xDC, 0xDE, 0xF8, 0xD3, 0xD6, 0xF5, 0xB8,
+  0xBA, 0xE2, 0xD7, 0xD7, 0xDB, 0xE9, 0xD6, 0xCF,
+  0xEA, 0xB3, 0xA5, 0xB5, 0x87, 0x7D, 0x7D, 0x7E,
+  0x92, 0xA4, 0xA7, 0xD4, 0xC4, 0xC6, 0xEC, 0xBE,
+  0xC1, 0xE8, 0xA3, 0xA6, 0xD5, 0x7E, 0x7F, 0x92,
+  0xC8, 0xC8, 0xD4, 0xEF, 0xE1, 0xDB, 0xBA, 0x77,
+  0x61, 0xEA, 0xAF, 0xA1, 0xD1, 0x92, 0x7E, 0xB2,
+  0x6E, 0x55, 0x8E, 0x57, 0x3B, 0x79, 0x7B, 0x8E,
+  0x84, 0x85, 0x98, 0x9F, 0xA0, 0xAE, 0xD2, 0xD2,
+  0xDD, 0xE4, 0xCF, 0xC6, 0xBF, 0x7E, 0x6A, 0xED,
+  0xB9, 0xAE, 0xD4, 0x96, 0x81, 0xB4, 0x6E, 0x54,
+  0xB7, 0xB5, 0xB4, 0xE8, 0xE8, 0xE8, 0xDA, 0xDA,
+  0xE1, 0xD7, 0xD7, 0xE0, 0xEE, 0xEE, 0xEE, 0xEB,
+  0xDB, 0xD6, 0xBC, 0x79, 0x64, 0xEE, 0xB7, 0xAB,
+  0xD1, 0x90, 0x7F, 0x82, 0x56, 0x40, 0xF1, 0xE5,
+  0xE2, 0xD8, 0x93, 0x84, 0xB3, 0x6D, 0x56, 0x90,
+  0x6A, 0x58, 0xAB, 0xA2, 0xA0, 0xED, 0xED, 0xED,
+  0xE4, 0xC4, 0xBD, 0xB7, 0x75, 0x5F, 0xA5, 0x76,
+  0x5D, 0xC1, 0xB9, 0xB5, 0xEA, 0xEA, 0xEA, 0xE8,
+  0xE1, 0xDD, 0xD6, 0xD1, 0xCE, 0xFF, 0xFF, 0xFF,
+  0x97, 0x1D, 0x8F, 0xA5, 0x00, 0x00, 0x00, 0x01,
+  0x74, 0x52, 0x4E, 0x53, 0x00, 0x40, 0xE6, 0xD8,
+  0x66, 0x00, 0x00, 0x00, 0x01, 0x62, 0x4B, 0x47,
+  0x44, 0x00, 0x88, 0x05, 0x1D, 0x48, 0x00, 0x00,
+  0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00,
+  0x0B, 0x13, 0x00, 0x00, 0x0B, 0x13, 0x01, 0x00,
+  0x9A, 0x9C, 0x18, 0x00, 0x00, 0x00, 0x07, 0x74,
+  0x49, 0x4D, 0x45, 0x07, 0xDC, 0x0C, 0x19, 0x08,
+  0x0E, 0x2E, 0x0D, 0x8F, 0xF2, 0x19, 0x00, 0x00,
+  0x00, 0xAE, 0x49, 0x44, 0x41, 0x54, 0x18, 0xD3,
+  0x63, 0x60, 0x80, 0x02, 0x46, 0x26, 0x66, 0x16,
+  0x56, 0x06, 0x04, 0x60, 0x63, 0xE7, 0xE0, 0xE4,
+  0xE2, 0xE6, 0x81, 0xF3, 0xF9, 0xF8, 0x05, 0x04,
+  0x85, 0x04, 0x85, 0x45, 0x44, 0xA1, 0x7C, 0x71,
+  0x09, 0x49, 0x29, 0x69, 0x19, 0x19, 0x29, 0x59,
+  0x39, 0x79, 0x88, 0x80, 0x82, 0xA2, 0x90, 0x92,
+  0xB2, 0x8A, 0xAA, 0x9A, 0x10, 0x87, 0x3A, 0x44,
+  0x40, 0x43, 0x53, 0x4A, 0x4B, 0x5B, 0x47, 0x47,
+  0x57, 0x8F, 0x53, 0x1F, 0x22, 0x60, 0xA0, 0x68,
+  0xA8, 0x65, 0x64, 0x6C, 0x62, 0x6A, 0x66, 0x6E,
+  0x01, 0x11, 0xB0, 0xB4, 0xB2, 0xB6, 0xB1, 0xB5,
+  0xB3, 0xB3, 0x77, 0x70, 0x74, 0x82, 0x08, 0xB8,
+  0xB8, 0x8A, 0xB8, 0xB9, 0x7B, 0x78, 0x78, 0x7A,
+  0xB9, 0x42, 0xF9, 0xBE, 0x7E, 0xFE, 0x01, 0x8A,
+  0x81, 0x41, 0xC1, 0x21, 0xA1, 0x60, 0x7E, 0x78,
+  0x44, 0x64, 0x54, 0xB4, 0x85, 0x7F, 0x4C, 0x6C,
+  0x5C, 0x3C, 0x98, 0x9F, 0x98, 0x94, 0x9C, 0x12,
+  0x9D, 0xCA, 0x90, 0x1E, 0x9F, 0x01, 0x51, 0x9F,
+  0x9D, 0x93, 0xEB, 0x92, 0x97, 0x8A, 0xE4, 0x8B,
+  0xEC, 0x82, 0xC2, 0xA2, 0x62, 0x24, 0x3E, 0x43,
+  0x69, 0x59, 0x79, 0x05, 0x03, 0x1E, 0x00, 0x00,
+  0xEF, 0xB6, 0x1D, 0x34, 0xD6, 0x6E, 0xFE, 0x41,
+  0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4E, 0x44,
+  0xAE, 0x42, 0x60, 0x82};
+/* End Of File */
Index: librapidsvn/src/rapidsvn.fbp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/rapidsvn.fbp=09(revision 5)
+++ librapidsvn/src/rapidsvn.fbp=09(working copy)
@@ -9801,11 +9801,313 @@
                                         <property name=3D"proportion">1</p=
roperty>
                                         <object class=3D"wxBoxSizer" expan=
ded=3D"0">
                                             <property name=3D"minimum_size=
"></property>
-                                            <property name=3D"name">upperL=
eftSizer</property>
+                                            <property name=3D"name">m_uppe=
rLeftSizer</property>
                                             <property name=3D"orient">wxVE=
RTICAL</property>
-                                            <property name=3D"permission">=
none</property>
+                                            <property name=3D"permission">=
protected</property>
                                             <object class=3D"sizeritem" ex=
panded=3D"1">
                                                 <property name=3D"border">=
5</property>
+                                                <property name=3D"flag">wx=
EXPAND</property>
+                                                <property name=3D"proporti=
on">0</property>
+                                                <object class=3D"wxBoxSize=
r" expanded=3D"1">
+                                                    <property name=3D"mini=
mum_size">-1,-1</property>
+                                                    <property name=3D"name=
">m_searchSizer</property>
+                                                    <property name=3D"orie=
nt">wxHORIZONTAL</property>
+                                                    <property name=3D"perm=
ission">protected</property>
+                                                    <object class=3D"sizer=
item" expanded=3D"1">
+                                                        <property name=3D"=
border">5</property>
+                                                        <property name=3D"=
flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
+                                                        <property name=3D"=
proportion">0</property>
+                                                        <object class=3D"w=
xStaticText" expanded=3D"1">
+                                                            <property name=
=3D"bg"></property>
+                                                            <property name=
=3D"context_help"></property>
+                                                            <property name=
=3D"enabled">1</property>
+                                                            <property name=
=3D"fg"></property>
+                                                            <property name=
=3D"font"></property>
+                                                            <property name=
=3D"hidden">0</property>
+                                                            <property name=
=3D"id">wxID_ANY</property>
+                                                            <property name=
=3D"label">Search</property>
+                                                            <property name=
=3D"maximum_size"></property>
+                                                            <property name=
=3D"minimum_size"></property>
+                                                            <property name=
=3D"name">m_staticSearch</property>
+                                                            <property name=
=3D"permission">protected</property>
+                                                            <property name=
=3D"pos"></property>
+                                                            <property name=
=3D"size"></property>
+                                                            <property name=
=3D"style"></property>
+                                                            <property name=
=3D"subclass"></property>
+                                                            <property name=
=3D"tooltip"></property>
+                                                            <property name=
=3D"validator_data_type"></property>
+                                                            <property name=
=3D"validator_style">wxFILTER_NONE</property>
+                                                            <property name=
=3D"validator_type">wxDefaultValidator</property>
+                                                            <property name=
=3D"validator_variable"></property>
+                                                            <property name=
=3D"window_extra_style"></property>
+                                                            <property name=
=3D"window_name"></property>
+                                                            <property name=
=3D"window_style"></property>
+                                                            <property name=
=3D"wrap">-1</property>
+                                                            <event name=3D=
"OnChar"></event>
+                                                            <event name=3D=
"OnEnterWindow"></event>
+                                                            <event name=3D=
"OnEraseBackground"></event>
+                                                            <event name=3D=
"OnKeyDown"></event>
+                                                            <event name=3D=
"OnKeyUp"></event>
+                                                            <event name=3D=
"OnKillFocus"></event>
+                                                            <event name=3D=
"OnLeaveWindow"></event>
+                                                            <event name=3D=
"OnLeftDClick"></event>
+                                                            <event name=3D=
"OnLeftDown"></event>
+                                                            <event name=3D=
"OnLeftUp"></event>
+                                                            <event name=3D=
"OnMiddleDClick"></event>
+                                                            <event name=3D=
"OnMiddleDown"></event>
+                                                            <event name=3D=
"OnMiddleUp"></event>
+                                                            <event name=3D=
"OnMotion"></event>
+                                                            <event name=3D=
"OnMouseEvents"></event>
+                                                            <event name=3D=
"OnMouseWheel"></event>
+                                                            <event name=3D=
"OnPaint"></event>
+                                                            <event name=3D=
"OnRightDClick"></event>
+                                                            <event name=3D=
"OnRightDown"></event>
+                                                            <event name=3D=
"OnRightUp"></event>
+                                                            <event name=3D=
"OnSetFocus"></event>
+                                                            <event name=3D=
"OnSize"></event>
+                                                            <event name=3D=
"OnUpdateUI"></event>
+                                                        </object>
+                                                    </object>
+                                                    <object class=3D"sizer=
item" expanded=3D"1">
+                                                        <property name=3D"=
border">5</property>
+                                                        <property name=3D"=
flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
+                                                        <property name=3D"=
proportion">1</property>
+                                                        <object class=3D"w=
xTextCtrl" expanded=3D"1">
+                                                            <property name=
=3D"bg"></property>
+                                                            <property name=
=3D"context_help"></property>
+                                                            <property name=
=3D"enabled">1</property>
+                                                            <property name=
=3D"fg"></property>
+                                                            <property name=
=3D"font"></property>
+                                                            <property name=
=3D"hidden">0</property>
+                                                            <property name=
=3D"id">wxID_ANY</property>
+                                                            <property name=
=3D"maximum_size"></property>
+                                                            <property name=
=3D"maxlength">0</property>
+                                                            <property name=
=3D"minimum_size"></property>
+                                                            <property name=
=3D"name">m_textSearch</property>
+                                                            <property name=
=3D"permission">protected</property>
+                                                            <property name=
=3D"pos"></property>
+                                                            <property name=
=3D"size"></property>
+                                                            <property name=
=3D"style"></property>
+                                                            <property name=
=3D"subclass"></property>
+                                                            <property name=
=3D"tooltip"></property>
+                                                            <property name=
=3D"validator_data_type"></property>
+                                                            <property name=
=3D"validator_style">wxFILTER_NONE</property>
+                                                            <property name=
=3D"validator_type">wxDefaultValidator</property>
+                                                            <property name=
=3D"validator_variable"></property>
+                                                            <property name=
=3D"value"></property>
+                                                            <property name=
=3D"window_extra_style"></property>
+                                                            <property name=
=3D"window_name"></property>
+                                                            <property name=
=3D"window_style"></property>
+                                                            <event name=3D=
"OnChar"></event>
+                                                            <event name=3D=
"OnEnterWindow"></event>
+                                                            <event name=3D=
"OnEraseBackground"></event>
+                                                            <event name=3D=
"OnKeyDown"></event>
+                                                            <event name=3D=
"OnKeyUp"></event>
+                                                            <event name=3D=
"OnKillFocus"></event>
+                                                            <event name=3D=
"OnLeaveWindow"></event>
+                                                            <event name=3D=
"OnLeftDClick"></event>
+                                                            <event name=3D=
"OnLeftDown"></event>
+                                                            <event name=3D=
"OnLeftUp"></event>
+                                                            <event name=3D=
"OnMiddleDClick"></event>
+                                                            <event name=3D=
"OnMiddleDown"></event>
+                                                            <event name=3D=
"OnMiddleUp"></event>
+                                                            <event name=3D=
"OnMotion"></event>
+                                                            <event name=3D=
"OnMouseEvents"></event>
+                                                            <event name=3D=
"OnMouseWheel"></event>
+                                                            <event name=3D=
"OnPaint"></event>
+                                                            <event name=3D=
"OnRightDClick"></event>
+                                                            <event name=3D=
"OnRightDown"></event>
+                                                            <event name=3D=
"OnRightUp"></event>
+                                                            <event name=3D=
"OnSetFocus"></event>
+                                                            <event name=3D=
"OnSize"></event>
+                                                            <event name=3D=
"OnText"></event>
+                                                            <event name=3D=
"OnTextEnter">OnSearchEnter</event>
+                                                            <event name=3D=
"OnTextMaxLen"></event>
+                                                            <event name=3D=
"OnTextURL"></event>
+                                                            <event name=3D=
"OnUpdateUI"></event>
+                                                        </object>
+                                                    </object>
+                                                    <object class=3D"sizer=
item" expanded=3D"1">
+                                                        <property name=3D"=
border">5</property>
+                                                        <property name=3D"=
flag">wxALL</property>
+                                                        <property name=3D"=
proportion">0</property>
+                                                        <object class=3D"w=
xChoice" expanded=3D"1">
+                                                            <property name=
=3D"bg"></property>
+                                                            <property name=
=3D"choices">&quot;author&quot; &quot;comment&quot; &quot;path&quot;</prope=
rty>
+                                                            <property name=
=3D"context_help"></property>
+                                                            <property name=
=3D"enabled">1</property>
+                                                            <property name=
=3D"fg"></property>
+                                                            <property name=
=3D"font"></property>
+                                                            <property name=
=3D"hidden">0</property>
+                                                            <property name=
=3D"id">wxID_ANY</property>
+                                                            <property name=
=3D"maximum_size"></property>
+                                                            <property name=
=3D"minimum_size"></property>
+                                                            <property name=
=3D"name">m_searchType</property>
+                                                            <property name=
=3D"permission">protected</property>
+                                                            <property name=
=3D"pos"></property>
+                                                            <property name=
=3D"selection">2</property>
+                                                            <property name=
=3D"size"></property>
+                                                            <property name=
=3D"subclass"></property>
+                                                            <property name=
=3D"tooltip"></property>
+                                                            <property name=
=3D"validator_data_type"></property>
+                                                            <property name=
=3D"validator_style">wxFILTER_NONE</property>
+                                                            <property name=
=3D"validator_type">wxDefaultValidator</property>
+                                                            <property name=
=3D"validator_variable"></property>
+                                                            <property name=
=3D"window_extra_style"></property>
+                                                            <property name=
=3D"window_name"></property>
+                                                            <property name=
=3D"window_style"></property>
+                                                            <event name=3D=
"OnChar"></event>
+                                                            <event name=3D=
"OnChoice"></event>
+                                                            <event name=3D=
"OnEnterWindow"></event>
+                                                            <event name=3D=
"OnEraseBackground"></event>
+                                                            <event name=3D=
"OnKeyDown"></event>
+                                                            <event name=3D=
"OnKeyUp"></event>
+                                                            <event name=3D=
"OnKillFocus"></event>
+                                                            <event name=3D=
"OnLeaveWindow"></event>
+                                                            <event name=3D=
"OnLeftDClick"></event>
+                                                            <event name=3D=
"OnLeftDown"></event>
+                                                            <event name=3D=
"OnLeftUp"></event>
+                                                            <event name=3D=
"OnMiddleDClick"></event>
+                                                            <event name=3D=
"OnMiddleDown"></event>
+                                                            <event name=3D=
"OnMiddleUp"></event>
+                                                            <event name=3D=
"OnMotion"></event>
+                                                            <event name=3D=
"OnMouseEvents"></event>
+                                                            <event name=3D=
"OnMouseWheel"></event>
+                                                            <event name=3D=
"OnPaint"></event>
+                                                            <event name=3D=
"OnRightDClick"></event>
+                                                            <event name=3D=
"OnRightDown"></event>
+                                                            <event name=3D=
"OnRightUp"></event>
+                                                            <event name=3D=
"OnSetFocus"></event>
+                                                            <event name=3D=
"OnSize"></event>
+                                                            <event name=3D=
"OnUpdateUI"></event>
+                                                        </object>
+                                                    </object>
+                                                    <object class=3D"sizer=
item" expanded=3D"1">
+                                                        <property name=3D"=
border">1</property>
+                                                        <property name=3D"=
flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
+                                                        <property name=3D"=
proportion">0</property>
+                                                        <object class=3D"w=
xBitmapButton" expanded=3D"1">
+                                                            <property name=
=3D"bg"></property>
+                                                            <property name=
=3D"bitmap"></property>
+                                                            <property name=
=3D"context_help"></property>
+                                                            <property name=
=3D"default">0</property>
+                                                            <property name=
=3D"disabled"></property>
+                                                            <property name=
=3D"enabled">1</property>
+                                                            <property name=
=3D"fg"></property>
+                                                            <property name=
=3D"focus"></property>
+                                                            <property name=
=3D"font"></property>
+                                                            <property name=
=3D"hidden">0</property>
+                                                            <property name=
=3D"hover"></property>
+                                                            <property name=
=3D"id">wxID_ANY</property>
+                                                            <property name=
=3D"label">Search</property>
+                                                            <property name=
=3D"maximum_size"></property>
+                                                            <property name=
=3D"minimum_size"></property>
+                                                            <property name=
=3D"name">m_buttonSearch</property>
+                                                            <property name=
=3D"permission">protected</property>
+                                                            <property name=
=3D"pos"></property>
+                                                            <property name=
=3D"selected"></property>
+                                                            <property name=
=3D"size"></property>
+                                                            <property name=
=3D"style">wxBU_AUTODRAW</property>
+                                                            <property name=
=3D"subclass"></property>
+                                                            <property name=
=3D"tooltip"></property>
+                                                            <property name=
=3D"validator_data_type"></property>
+                                                            <property name=
=3D"validator_style">wxFILTER_NONE</property>
+                                                            <property name=
=3D"validator_type">wxDefaultValidator</property>
+                                                            <property name=
=3D"validator_variable"></property>
+                                                            <property name=
=3D"window_extra_style"></property>
+                                                            <property name=
=3D"window_name"></property>
+                                                            <property name=
=3D"window_style"></property>
+                                                            <event name=3D=
"OnButtonClick">OnSearch</event>
+                                                            <event name=3D=
"OnChar"></event>
+                                                            <event name=3D=
"OnEnterWindow"></event>
+                                                            <event name=3D=
"OnEraseBackground"></event>
+                                                            <event name=3D=
"OnKeyDown"></event>
+                                                            <event name=3D=
"OnKeyUp"></event>
+                                                            <event name=3D=
"OnKillFocus"></event>
+                                                            <event name=3D=
"OnLeaveWindow"></event>
+                                                            <event name=3D=
"OnLeftDClick"></event>
+                                                            <event name=3D=
"OnLeftDown"></event>
+                                                            <event name=3D=
"OnLeftUp"></event>
+                                                            <event name=3D=
"OnMiddleDClick"></event>
+                                                            <event name=3D=
"OnMiddleDown"></event>
+                                                            <event name=3D=
"OnMiddleUp"></event>
+                                                            <event name=3D=
"OnMotion"></event>
+                                                            <event name=3D=
"OnMouseEvents"></event>
+                                                            <event name=3D=
"OnMouseWheel"></event>
+                                                            <event name=3D=
"OnPaint"></event>
+                                                            <event name=3D=
"OnRightDClick"></event>
+                                                            <event name=3D=
"OnRightDown"></event>
+                                                            <event name=3D=
"OnRightUp"></event>
+                                                            <event name=3D=
"OnSetFocus"></event>
+                                                            <event name=3D=
"OnSize"></event>
+                                                            <event name=3D=
"OnUpdateUI"></event>
+                                                        </object>
+                                                    </object>
+                                                    <object class=3D"sizer=
item" expanded=3D"1">
+                                                        <property name=3D"=
border">1</property>
+                                                        <property name=3D"=
flag">wxALIGN_CENTER_VERTICAL|wxALL</property>
+                                                        <property name=3D"=
proportion">0</property>
+                                                        <object class=3D"w=
xBitmapButton" expanded=3D"1">
+                                                            <property name=
=3D"bg"></property>
+                                                            <property name=
=3D"bitmap"></property>
+                                                            <property name=
=3D"context_help"></property>
+                                                            <property name=
=3D"default">0</property>
+                                                            <property name=
=3D"disabled"></property>
+                                                            <property name=
=3D"enabled">1</property>
+                                                            <property name=
=3D"fg"></property>
+                                                            <property name=
=3D"focus"></property>
+                                                            <property name=
=3D"font"></property>
+                                                            <property name=
=3D"hidden">0</property>
+                                                            <property name=
=3D"hover"></property>
+                                                            <property name=
=3D"id">wxID_ANY</property>
+                                                            <property name=
=3D"label">Reindex</property>
+                                                            <property name=
=3D"maximum_size"></property>
+                                                            <property name=
=3D"minimum_size"></property>
+                                                            <property name=
=3D"name">m_buttonReindex</property>
+                                                            <property name=
=3D"permission">protected</property>
+                                                            <property name=
=3D"pos"></property>
+                                                            <property name=
=3D"selected"></property>
+                                                            <property name=
=3D"size"></property>
+                                                            <property name=
=3D"style">wxBU_AUTODRAW</property>
+                                                            <property name=
=3D"subclass"></property>
+                                                            <property name=
=3D"tooltip"></property>
+                                                            <property name=
=3D"validator_data_type"></property>
+                                                            <property name=
=3D"validator_style">wxFILTER_NONE</property>
+                                                            <property name=
=3D"validator_type">wxDefaultValidator</property>
+                                                            <property name=
=3D"validator_variable"></property>
+                                                            <property name=
=3D"window_extra_style"></property>
+                                                            <property name=
=3D"window_name"></property>
+                                                            <property name=
=3D"window_style"></property>
+                                                            <event name=3D=
"OnButtonClick">OnReindex</event>
+                                                            <event name=3D=
"OnChar"></event>
+                                                            <event name=3D=
"OnEnterWindow"></event>
+                                                            <event name=3D=
"OnEraseBackground"></event>
+                                                            <event name=3D=
"OnKeyDown"></event>
+                                                            <event name=3D=
"OnKeyUp"></event>
+                                                            <event name=3D=
"OnKillFocus"></event>
+                                                            <event name=3D=
"OnLeaveWindow"></event>
+                                                            <event name=3D=
"OnLeftDClick"></event>
+                                                            <event name=3D=
"OnLeftDown"></event>
+                                                            <event name=3D=
"OnLeftUp"></event>
+                                                            <event name=3D=
"OnMiddleDClick"></event>
+                                                            <event name=3D=
"OnMiddleDown"></event>
+                                                            <event name=3D=
"OnMiddleUp"></event>
+                                                            <event name=3D=
"OnMotion"></event>
+                                                            <event name=3D=
"OnMouseEvents"></event>
+                                                            <event name=3D=
"OnMouseWheel"></event>
+                                                            <event name=3D=
"OnPaint"></event>
+                                                            <event name=3D=
"OnRightDClick"></event>
+                                                            <event name=3D=
"OnRightDown"></event>
+                                                            <event name=3D=
"OnRightUp"></event>
+                                                            <event name=3D=
"OnSetFocus"></event>
+                                                            <event name=3D=
"OnSize"></event>
+                                                            <event name=3D=
"OnUpdateUI"></event>
+                                                        </object>
+                                                    </object>
+                                                </object>
+                                            </object>
+                                            <object class=3D"sizeritem" ex=
panded=3D"1">
+                                                <property name=3D"border">=
5</property>
                                                 <property name=3D"flag">wx=
ALL</property>
                                                 <property name=3D"proporti=
on">0</property>
                                                 <object class=3D"wxStaticT=
ext" expanded=3D"1">
Index: librapidsvn/src/log_action.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/log_action.cpp=09(revision 5)
+++ librapidsvn/src/log_action.cpp=09(working copy)
@@ -38,6 +38,8 @@
 #include "ids.hpp"
 #include "log_action.hpp"
 #include "log_data.hpp"
+#include "repository_searcher_builder.hpp"
+#include "utils.hpp"
=20
 LogAction::LogAction(wxWindow * parent)
     : Action(parent, _("Log"), DONT_UPDATE)
@@ -53,8 +55,23 @@
   const svn::LogEntries * entries =3D
     client.log(target.c_str(), svn::Revision::START,
                svn::Revision::HEAD, true, false);
+  svn::RepositoryPath repositoryPath =3D CreateRepositoryPath(client, targ=
et);
+  RepositorySearcherIface *searcher =3D NULL;
=20
-  LogData * data =3D new LogData(entries, CreateRepositoryPath(client, tar=
get));
+  try
+  {
+    searcher =3D RepositorySearcherBuilder::getInstance().getOrCreateSearc=
her(GetContext(), repositoryPath.getRepositoryRoot());
+    if (searcher !=3D NULL)
+    {
+      searcher->update(entries);
+    }
+  }
+  catch (SearcherException e)
+  {
+    TraceError(Utf8ToLocal(e.getMessage()));
+  }
+
+  LogData * data =3D new LogData(entries, repositoryPath, searcher);
   ActionEvent::Post(GetParent(), TOKEN_LOG, data);
=20
   return true;
Index: librapidsvn/src/repository_searcher.cpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/src/repository_searcher.cpp=09(revision 0)
+++ librapidsvn/src/repository_searcher.cpp=09(revision 0)
@@ -0,0 +1,309 @@
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ * Copyright (c) 2002-2012 The RapidSVN Group.  All rights reserved.
+ *
+ * This program 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.
+ *
+ * This program 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 this program (in the file GPL.txt.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://rapidsvn.tigris.org/.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ */
+
+#if HAVE_SQLITE3_H
+
+// svncpp
+#include "svncpp/client.hpp"
+#include "svncpp/log_entry.hpp"
+
+#include "repository_searcher.hpp"
+
+namespace
+{
+  class SQLiteStatement
+  {
+  public:
+    SQLiteStatement(sqlite3 *db, std::string const & query)
+      : m_db(db), m_query(query)
+    {
+      prepare();
+    }
+
+    ~SQLiteStatement()
+    {
+      sqlite3_finalize(m_stmt);
+    }
+
+    void bindText(std::string const & parameter, std::string const & value=
)
+    {
+      int index =3D sqlite3_bind_parameter_index(m_stmt, parameter.c_str()=
);
+      sqlite3_bind_text(m_stmt, index, value.c_str(), -1, SQLITE_TRANSIENT=
);
+    }
+
+    void bindInt64(std::string const & parameter, sqlite3_int64 value)
+    {
+      int index =3D sqlite3_bind_parameter_index(m_stmt, parameter.c_str()=
);
+      sqlite3_bind_int64(m_stmt, index, value);
+    }
+
+    bool step()
+    {
+      int result =3D sqlite3_step(m_stmt);
+      if (result !=3D SQLITE_DONE && result !=3D SQLITE_ROW)
+      {
+        throw DatabaseException(std::string("Cannot execute statement: ") =
+ sqlite3_errmsg(m_db));
+      }
+      return result =3D=3D SQLITE_ROW;
+    }
+
+    bool executeAndReset()
+    {
+      bool result =3D step();
+      sqlite3_reset(m_stmt);
+      return result;
+    }
+
+    sqlite3_int64 getInt64(int columnIndex =3D 0)
+    {
+      return sqlite3_column_int64(m_stmt, columnIndex);
+    }
+
+  private:
+    sqlite3 *m_db;
+    sqlite3_stmt *m_stmt;
+    std::string m_query;
+
+    void prepare()
+    {
+      int result =3D sqlite3_prepare_v2(m_db, m_query.c_str(), -1, &m_stmt=
, NULL);
+      if (result !=3D SQLITE_OK)
+      {
+        throw DatabaseException("Cannot prepare statement '" + m_query + "=
': " + sqlite3_errmsg(m_db));
+      }
+    }
+  };
+
+  class SQLiteTransaction
+  {
+  public:
+    SQLiteTransaction(sqlite3 *db)
+    {
+      m_db =3D db;
+      begin();
+    }
+
+    ~SQLiteTransaction()
+    {
+      if (!finished)
+        commit();
+    }
+
+    void commit()
+    {
+      finished =3D true;
+      sqlite3_exec(m_db, "COMMIT", NULL, NULL, NULL);    =20
+    }
+
+    void rollback()
+    {
+      finished =3D true;
+      sqlite3_exec(m_db, "ROLLBACK", NULL, NULL, NULL);    =20
+    }
+  private:
+    sqlite3 *m_db;
+    bool finished;
+
+    void begin()
+    {
+      finished =3D false;
+      sqlite3_exec(m_db, "BEGIN", NULL, NULL, NULL);    =20
+    }
+  };
+
+  void
+  insertEachRevisionAndPath(SQLiteStatement & insertStatement, svn::LogEnt=
ry const & entry)
+  {
+    insertStatement.bindInt64(":revision", entry.revision);
+    for (svn::LogEntry::ChangePathCollection::const_iterator it =3D entry.=
changedPaths.begin(); it !=3D entry.changedPaths.end(); ++it)
+    {
+      insertStatement.bindText(":path", it->path);
+      insertStatement.executeAndReset();
+    }
+  }
+}
+
+RepositorySearcher::RepositorySearcher(svn::Context * context, std::string=
 const & repositoryPath)
+: m_client(context), m_repositoryPath(repositoryPath)
+{
+}
+
+void
+RepositorySearcher::openDatabase(const std::string & dataDirectory)
+{
+  std::string fileName =3D getDatabaseFileName(dataDirectory);
+  int result =3D sqlite3_open_v2(
+      fileName.c_str(),
+      &m_db,
+      SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
+      NULL);
+  if (result !=3D SQLITE_OK)
+  {
+    throw DatabaseException(std::string("Cannot open database: ") + sqlite=
3_errmsg(m_db));
+  }
+}
+
+void
+RepositorySearcher::createTablesIfNotExist()
+{
+  const char * tablesDdl =3D
+    "CREATE TABLE IF NOT EXISTS revisions (revision INTEGER PRIMARY KEY, a=
uthor VARCHAR(64), message TEXT); "
+    "CREATE TABLE IF NOT EXISTS affectedFiles (id INTEGER PRIMARY KEY AUTO=
INCREMENT, revision INTEGER, path VARCHAR(1024), FOREIGN KEY(revision) REFE=
RENCES revisions(revision))";
+  char * error =3D "";
+
+  int result =3D sqlite3_exec(
+      m_db,
+      tablesDdl,
+      NULL,
+      NULL,
+      &error);
+  if (result !=3D SQLITE_OK)
+  {
+    throw DatabaseException(std::string("Cannot create tables: ") + error)=
;
+  }
+}
+
+std::set<svn_revnum_t>
+RepositorySearcher::search(const std::string & query, SearchType searchTyp=
e) const
+{
+  const char *queries[] =3D
+  {
+    "SELECT DISTINCT revision FROM revisions WHERE author LIKE :query",
+    "SELECT DISTINCT revision FROM revisions WHERE message LIKE :query",
+    "SELECT DISTINCT revision FROM affectedFiles WHERE path LIKE :query"
+  };
+  SQLiteStatement pathQuery(m_db, queries[searchType]);
+  std::set<svn_revnum_t> result;
+  pathQuery.bindText(":query", ("%" + query + "%").c_str());
+
+  while (pathQuery.step())
+  {
+    result.insert(pathQuery.getInt64());
+  }
+  return result;
+}
+
+void
+RepositorySearcher::update(const svn::LogEntries * entries)
+{
+  svn_revnum_t lastRevision =3D getLastCachedRevision();
+  if (entries->front().revision > lastRevision)
+    fillCache(svn::Revision(lastRevision + 1));
+}
+
+void
+RepositorySearcher::reindex()
+{
+  deleteCache();
+  fillCache();
+}
+
+void
+RepositorySearcher::deleteCache()
+{
+  const char * deleteTablesContent =3D
+    "DELETE FROM affectedFiles; "
+    "DELETE FROM revisions";
+  char *error =3D "";
+
+  int result =3D sqlite3_exec(
+      m_db,
+      deleteTablesContent,
+      NULL,
+      NULL,
+      &error);
+  if (result !=3D SQLITE_OK)
+  {
+    throw DatabaseException(std::string("Cannot delete tables content: ") =
+ error);
+  }
+}
+
+void
+RepositorySearcher::fillCache(svn::Revision const & fromRevision)
+{
+  const svn::LogEntries * entries =3D
+    m_client.log(m_repositoryPath.c_str(), fromRevision, svn::Revision::HE=
AD, true, false);
+
+  if (entries =3D=3D NULL)
+    return;
+
+  SQLiteTransaction transaction(m_db);
+  SQLiteStatement revisionInsert(m_db, "INSERT INTO revisions (revision, a=
uthor, message) VALUES (:revision, :author, :message)");
+  SQLiteStatement affectedFilesInsert(m_db, "INSERT INTO affectedFiles (re=
vision, path) VALUES (:revision, :path)");
+
+  for (svn::LogEntries::const_iterator it =3D entries->begin(); it !=3D en=
tries->end(); ++it)
+  {
+    revisionInsert.bindInt64(":revision", it->revision);
+    revisionInsert.bindText(":author", it->author);
+    revisionInsert.bindText(":message", it->message);
+    revisionInsert.executeAndReset();
+
+    insertEachRevisionAndPath(affectedFilesInsert, *it);
+  }
+}
+
+svn_revnum_t
+RepositorySearcher::getLastCachedRevision()
+{
+  SQLiteStatement lastRevisionStatement(m_db, "SELECT MAX(revision) FROM r=
evisions");
+
+  if (lastRevisionStatement.step())
+    return lastRevisionStatement.getInt64();
+
+  return 0;
+}
+
+std::string
+RepositorySearcher::getDatabaseFileName(std::string const & dataDirectory)=
 const
+{
+  std::string fileName =3D m_repositoryPath;
+  fileName =3D sanitizeFileName(fileName) + ".db";
+  return dataDirectory + "/" + fileName;
+}
+
+std::string
+RepositorySearcher::sanitizeFileName(std::string const & string) const
+{
+  std::string result(string);
+  for (size_t index =3D 0; index < result.length(); index++)
+  {
+    switch (result[index])
+    {
+    case '/':
+    case '\\':
+    case ':':
+      result[index] =3D '_';
+      break;
+    }
+  }
+  return result;
+}
+
+#endif // HAVE_SQLITE3_H
+
+/* -----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../rapidsvn-dev.el")
+ * end:
+ */
Index: librapidsvn/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/Makefile.am=09(revision 2)
+++ librapidsvn/Makefile.am=09(working copy)
@@ -79,9 +79,13 @@
 =09include/property_action.hpp \
 =09include/property_dlg.hpp \
 =09include/rapidsvn_app.hpp \
+=09include/rapidsvn_config.hpp \
 =09include/rapidsvn_drop_target.hpp \
 =09include/rename_action.hpp \
 =09include/report_dlg.hpp \
+=09include/repository_searcher_builder.hpp \
+=09include/repository_searcher_iface.hpp \
+=09include/repository_searcher.hpp \
 =09include/resolve_action.hpp \
 =09include/resource.hpp \
 =09include/revert_action.hpp \
@@ -204,7 +208,7 @@
 librapidsvn_la_CPPFLAGS=3D-Iinclude -I$(SVNCPP_DIR)/include
 librapidsvn_la_DEPENDENCIES=3D$(SVNCPP_DIR)/libsvncpp.la
 librapidsvn_la_LDFLAGS=3D-version-info 0:0:0 \
-=09$(WX_LIBS)
+=09$(WX_LIBS) $(LIBSQLITE)
 librapidsvn_la_SOURCES=3D \
 =09src/about_dlg.cpp \
 =09src/action.cpp \
@@ -266,10 +270,13 @@
 =09src/preferences_dlg.cpp \
 =09src/property_action.cpp \
 =09src/property_dlg.cpp \
+=09src/rapidsvn_config.cpp \
 =09src/rapidsvn_drop_target.cpp \
 =09src/rapidsvn_generated.cpp \
 =09src/rename_action.cpp \
 =09src/report_dlg.cpp \
+=09src/repository_searcher_builder.cpp \
+=09src/repository_searcher.cpp \
 =09src/resolve_action.cpp \
 =09src/revert_action.cpp \
 =09src/revert_dlg.cpp \
Index: librapidsvn/include/repository_searcher_iface.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/repository_searcher_iface.hpp=09(revision 0)
+++ librapidsvn/include/repository_searcher_iface.hpp=09(revision 0)
@@ -0,0 +1,96 @@
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ * Copyright (c) 2002-2012 The RapidSVN Group.  All rights reserved.
+ *
+ * This program 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.
+ *
+ * This program 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 this program (in the file GPL.txt.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://rapidsvn.tigris.org/.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ */
+
+#ifndef _REPOSITORY_SEARCHER_IFACE_HPP_
+#define _REPOSITORY_SEARCHER_IFACE_HPP_
+
+#include <exception>
+#include <string>
+#include <set>
+
+// svncpp
+#include <svncpp/client.hpp>
+
+/**
+ * Derive from this class to deny class copying.
+ */
+class NonCopyable
+{
+public:
+  NonCopyable() {}
+
+private:
+  /**
+   * disallow assignment operator
+   */
+  NonCopyable & operator=3D (const NonCopyable &) { return *this; }
+
+  /**
+   * disallow copy constructor
+   */
+  NonCopyable(const NonCopyable &) {}
+};
+
+class SearcherException : public std::exception
+{
+public:
+  SearcherException(std::string const & message)
+    : m_message(message)
+    {
+    }
+
+  ~SearcherException() throw ()
+    {
+    }
+
+  const std::string & getMessage() const { return m_message; }
+
+private:
+  std::string m_message;
+};
+
+class RepositorySearcherIface : public NonCopyable
+{
+public:
+  enum SearchType
+  {
+    stAuthor =3D 0,
+    stComment,
+    stPath
+  };
+
+  virtual ~RepositorySearcherIface() {}
+
+  virtual std::set<svn_revnum_t> search(const std::string & query, SearchT=
ype searchType) const =3D 0;
+
+  virtual void update(const svn::LogEntries * entries) =3D 0;
+  virtual void reindex() =3D 0;
+};
+
+#endif // _REPOSITORY_SEARCHER_IFACE_HPP_
+/* -----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../rapidsvn-dev.el")
+ * end:
+ */
Index: librapidsvn/include/rapidsvn_generated.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/rapidsvn_generated.h=09(revision 5)
+++ librapidsvn/include/rapidsvn_generated.h=09(working copy)
@@ -41,6 +41,7 @@
 #include <wx/radiobut.h>
 #include <wx/datectrl.h>
 #include <wx/dateevt.h>
+#include <wx/bmpbuttn.h>
 #include <wx/splitter.h>
 #include <wx/treectrl.h>
 #include <wx/statusbr.h>
@@ -576,6 +577,13 @@
 =09=09wxBoxSizer* m_mainSizer;
 =09=09wxSplitterWindow* m_splitter;
 =09=09wxPanel* m_upperPanel;
+=09=09wxBoxSizer* m_upperLeftSizer;
+=09=09wxBoxSizer* m_searchSizer;
+=09=09wxStaticText* m_staticSearch;
+=09=09wxTextCtrl* m_textSearch;
+=09=09wxChoice* m_searchType;
+=09=09wxBitmapButton* m_buttonSearch;
+=09=09wxBitmapButton* m_buttonReindex;
 =09=09wxStaticText* m_staticRevisions;
 =09=09LogRevList* m_listRevisions;
 =09=09wxButton* m_buttonClose;
@@ -592,6 +600,9 @@
 =09=09LogAffectedList* m_listFiles;
 =09=09
 =09=09// Virtual event handlers, overide them in your derived class
+=09=09virtual void OnSearchEnter( wxCommandEvent& event ) { event.Skip(); =
}
+=09=09virtual void OnSearch( wxCommandEvent& event ) { event.Skip(); }
+=09=09virtual void OnReindex( wxCommandEvent& event ) { event.Skip(); }
 =09=09virtual void OnRevDeselected( wxListEvent& event ) { event.Skip(); }
 =09=09virtual void OnRevSelected( wxListEvent& event ) { event.Skip(); }
 =09=09virtual void OnView( wxCommandEvent& event ) { event.Skip(); }
Index: librapidsvn/include/log_rev_list.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/log_rev_list.hpp=09(revision 3)
+++ librapidsvn/include/log_rev_list.hpp=09(working copy)
@@ -66,9 +66,18 @@
     if (entries =3D=3D 0)
       return;
=20
+    SetEntries(entries->begin(), entries->end());
+  }
+
+  template<class Iterator>
+  void SetEntries(Iterator begin, Iterator end)
+  {
     long index=3D0;
-    svn::LogEntries::const_iterator it;
-    for (it=3Dentries->begin(); it !=3D entries->end(); it++)
+    Iterator it;
+
+    DeleteAllItems();
+
+    for (it =3D begin; it !=3D end; ++it)
     {
       const svn::LogEntry & entry =3D *it;
       wxString rev;
Index: librapidsvn/include/repository_searcher.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/repository_searcher.hpp=09(revision 0)
+++ librapidsvn/include/repository_searcher.hpp=09(revision 0)
@@ -0,0 +1,83 @@
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ * Copyright (c) 2002-2012 The RapidSVN Group.  All rights reserved.
+ *
+ * This program 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.
+ *
+ * This program 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 this program (in the file GPL.txt.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://rapidsvn.tigris.org/.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ */
+
+#ifndef _REPOSITORY_SEARCHER_HPP_
+#define _REPOSITORY_SEARCHER_HPP_
+
+#include <sqlite3.h>
+
+// svncpp
+#include <svncpp/revision.hpp>
+
+// rapidsvn
+#include "repository_searcher_iface.hpp"
+
+namespace svn
+{
+  class Client;
+}
+
+class DatabaseException : public SearcherException
+{
+public:
+  DatabaseException(std::string const & message)
+    : SearcherException(message)
+    {
+    }
+
+  ~DatabaseException() throw ()
+    {
+    }
+};
+
+class RepositorySearcher : public RepositorySearcherIface
+{
+public:
+  RepositorySearcher(svn::Context * context, std::string const & repositor=
yPath);
+
+  std::set<svn_revnum_t> search(const std::string & query, SearchType sear=
chType) const;
+
+  void openDatabase(const std::string & dataDirectory);
+  void createTablesIfNotExist();
+  void update(const svn::LogEntries * entries);
+  void reindex();
+
+private:
+  svn::Client m_client;
+  std::string m_repositoryPath;
+  sqlite3 *m_db;
+
+  void deleteCache();
+  void fillCache(svn::Revision const & fromRevision =3D svn::Revision::STA=
RT);
+  svn_revnum_t getLastCachedRevision();
+  std::string getDatabaseFileName(std::string const & dataDirectory) const=
;
+  std::string sanitizeFileName(std::string const & string) const;
+};
+
+#endif // _REPOSITORY_SEARCHER_HPP_
+/* -----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../rapidsvn-dev.el")
+ * end:
+ */
Index: librapidsvn/include/log_data.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/log_data.hpp=09(revision 5)
+++ librapidsvn/include/log_data.hpp=09(working copy)
@@ -32,14 +32,17 @@
 #include "svncpp/client.hpp"
 #include "svncpp/repository_path.hpp"
=20
+#include "repository_searcher_iface.hpp"
+
 struct LogData
 {
 public:
   const svn::LogEntries * logEntries;
   svn::RepositoryPath target;
+  RepositorySearcherIface *searcher;
=20
-  LogData(const svn::LogEntries * logEntries_, const svn::RepositoryPath &=
 target_)
-      : logEntries(logEntries_), target(target_)
+  LogData(const svn::LogEntries * logEntries_, const svn::RepositoryPath &=
 target_, RepositorySearcherIface *searcher_)
+      : logEntries(logEntries_), target(target_), searcher(searcher_)
   {
   }
 };
Index: librapidsvn/include/repository_searcher_builder.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/repository_searcher_builder.hpp=09(revision 0)
+++ librapidsvn/include/repository_searcher_builder.hpp=09(revision 0)
@@ -0,0 +1,57 @@
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ * Copyright (c) 2002-2012 The RapidSVN Group.  All rights reserved.
+ *
+ * This program 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.
+ *
+ * This program 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 this program (in the file GPL.txt.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://rapidsvn.tigris.org/.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ */
+
+#ifndef _REPOSITORY_SEARCHER_BUILDER_HPP_
+#define _REPOSITORY_SEARCHER_BUILDER_HPP_
+
+#include "repository_searcher_iface.hpp"
+
+// stl
+#include <map>
+#include <string>
+
+class RepositorySearcherBuilder
+{
+public:
+  ~RepositorySearcherBuilder();
+
+  static void setUserDataDirectoryWithEndingSeparator(std::string const & =
directory);
+  static RepositorySearcherBuilder &getInstance();
+
+  RepositorySearcherIface *getOrCreateSearcher(svn::Context * context, std=
::string const & repositoryPath);
+
+private:
+  static std::string m_dataDirectory;
+
+  std::map<std::string, RepositorySearcherIface *> m_searchers;
+
+  RepositorySearcherBuilder() {}
+};
+
+#endif // _REPOSITORY_SEARCHER_BUILDER_HPP_
+/* -----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../rapidsvn-dev.el")
+ * end:
+ */
Index: librapidsvn/include/log_dlg.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/log_dlg.hpp=09(revision 8)
+++ librapidsvn/include/log_dlg.hpp=09(working copy)
@@ -38,6 +38,7 @@
=20
 // app
 #include "rapidsvn_generated.h"
+#include "repository_searcher_iface.hpp"
=20
 class LogDlg : public LogDlgBase
 {
@@ -49,10 +50,12 @@
    * @param parent parent window
    * @param path path of selected item
    * @param entries log entries
+   * @param searcher engine for log filtering
    */
   LogDlg(wxWindow * parent,
          const svn::RepositoryPath & path,=20
-         const svn::LogEntries * entries);
+         const svn::LogEntries * entries,
+         RepositorySearcherIface *searcher);
=20
   /**
    * destructor
@@ -82,6 +85,12 @@
   OnRevDeselected(wxListEvent & event);
=20
   void
+  OnSearch(wxCommandEvent & event);
+
+  void
+  OnReindex(wxCommandEvent & event);
+
+  void
   OnAffectedFileOrDirRightClick(wxListEvent & event);
=20
 private:
@@ -100,6 +109,7 @@
=20
   void CheckControls();
   void UpdateSelection();
+  void UpdateRevisionsList();
   void ReduceSelectionToOnlyTwoItems();
   void FillAffectedFiles();
   std::set<std::string> GetIntersectionOfAffectedPaths();
Index: librapidsvn/include/rapidsvn_config.hpp
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- librapidsvn/include/rapidsvn_config.hpp=09(revision 0)
+++ librapidsvn/include/rapidsvn_config.hpp=09(revision 0)
@@ -0,0 +1,47 @@
+/*
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ * Copyright (c) 2002-2012 The RapidSVN Group.  All rights reserved.
+ *
+ * This program 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.
+ *
+ * This program 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 this program (in the file GPL.txt.
+ * If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals.  For exact contribution history, see the revision
+ * history and logs, available at http://rapidsvn.tigris.org/.
+ * =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
+ */
+#ifndef _RAPIDSVN_CONFIG_H_INCLUDED_
+#define _RAPIDSVN_CONFIG_H_INCLUDED_
+
+class Config
+{
+public:
+  Config();
+
+  wxConfigBase *GetConfig();
+private:
+  void Init();
+  void CreateDataDirectoryIfMissing();
+  void MigrateOldConfiguration();
+
+  wxString m_userDataDir;
+  wxString m_cacheDir;
+};
+
+#endif // _RAPIDSVN_CONFIG_H_INCLUDED_
+/* -----------------------------------------------------------------
+ * local variables:
+ * eval: (load-file "../rapidsvn-dev.el")
+ * end:
+ */

------=_Part_778_1334681891.1356770011945
Content-Type: image/png; name=filteredit.png
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename=filteredit.png

iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAABd1BMVEXt7fPNzta1tcCnqLW4ucfL
zNe3uM20tti5vOe/wuu7vuOzttioqbvw8PS5us+3ueDGyfLJzPXLzvXFyPGxtOGrrLju7vDMzdOr
r9THyvPKzfbLzvfMz/bHyvGjpdTAwcm0tL67vufN0PfQ0/jU1/jV1/fS1fitrrmmp7TEx+7S1Pja
3Pjm5/rd3/nQ0vaOkKCgoa7LzfXi5Pr09Pz09fzk5vrU1va6veaVlqW/v8epq9TIy/LQ0/bf4Pnt
7vvi4/jQ0fSmqdW3t8Hu39q0bVSChJfJzPPU1/bc3vjT1vW4uuLX19vp1s/qs6W1h319fpKkp9TE
xuy+weijptV+f5LIyNTv4du6d2Hqr6HRkn6yblWOVzt5e46EhZifoK7S0t3kz8a/fmrtua7UloG0
blS3tbTo6Oja2uHX1+Du7u7r29a8eWTut6vRkH+CVkDx5eLYk4SzbVaQaliroqDt7e3kxL23dV+l
dl3BubXq6uro4d3W0c7///+XHY+lAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAA
CxMAAAsTAQCanBgAAAAHdElNRQfcDBkIDi4Nj/IZAAAArklEQVQY02NggAJGJmYWVgYEYGPn4OTi
5oHz+fgFBIUEhUVEoXxxCUkpaRkZKVk5eYiAgqKQkrKKqpoQhzpEQENTSktbR0dXj1MfImCgaKhl
ZGxiamZuARGwtLK2sbWzs3dwdIIIuLiKuLl7eHh6uUL5vn7+AYqBQcEhoWB+eERkVLSFf0xsXDyY
n5iUnBKdypAenwFRn52T65KXiuSL7ILComIkPkNpWXkFAx4AAO+2HTTWbv5BAAAAAElFTkSuQmCC

------=_Part_778_1334681891.1356770011945--

------=_Part_777_1699845876.1356770011945
Content-Type: application/pgp-signature; name=signature.asc
Content-Transfer-Encoding: 7bit
Content-Description: Digital signature
Content-Disposition: attachment; filename=signature.asc

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.12 (GNU/Linux)

iEYEARECAAYFAlDeqBoACgkQqyAtJTO7yRKLVwCfXKKNtyDbYkMmrfuNltD7p79v
QNUAn2wWmJ+r4AlzFCRNL7cYT3iF72lL
=GiUK
-----END PGP SIGNATURE-----

------=_Part_777_1699845876.1356770011945--