Index: includes/versioncontrol_views_handler_argument_path_terms.inc
===================================================================
--- includes/versioncontrol_views_handler_argument_path_terms.inc	(revision 0)
+++ includes/versioncontrol_views_handler_argument_path_terms.inc	(revision 0)
@@ -0,0 +1,19 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Version Control API Views Handler:  Argument "Path Terms"
+ */
+
+class versioncontrol_views_handler_argument_path_terms extends views_handler_argument_term_node_tid {
+  function query() {
+    $term = taxonomy_get_term(reset($this->value));
+    $term_flattened = str_replace(' ', '', $term->name);
+    $this->ensure_my_table();
+    $this->query->add_field('versioncontrol_operations', 'repo_id');
+    $this->query->add_field('versioncontrol_svn_repositories', 'path_trunk');
+    // ugly query to extract the actual path from the serialized 'path_trunk' field
+    $this->query->add_where($this->options['group'], "$this->table_alias.$this->real_field LIKE CONCAT(REPLACE(REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(versioncontrol_svn_repositories.path_trunk,'\"',-2),'\"',1),'%project','%s'),'*','%'),'%')", $term_flattened);
+  }
+}
Index: includes/versioncontrol_views_handler_field_path_terms.inc
===================================================================
--- includes/versioncontrol_views_handler_field_path_terms.inc	(revision 0)
+++ includes/versioncontrol_views_handler_field_path_terms.inc	(revision 0)
@@ -0,0 +1,24 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Version Control API Views Handler:  Field "Path Terms"
+ */
+
+class versioncontrol_views_handler_field_path_terms extends views_handler_field {
+  function query() {
+    $this->ensure_my_table();
+    $this->add_additional_fields(array('repo_id', 'revision'));
+    $this->query->ensure_table('versioncontrol_svn_repositories');
+    // ugly query to generate a comma-separated list of terms matching the serialized 'path_trunk' field
+    $this->query->add_field(NULL, "(SELECT CAST(GROUP_CONCAT(DISTINCT(tid)) AS CHAR) FROM term_data t, versioncontrol_item_revisions r WHERE r.path LIKE CONCAT(REPLACE(REPLACE(REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(versioncontrol_svn_repositories.path_trunk,'\"',-2),'\"',1),' ',''),'%project',REPLACE(t.name,' ','')),'*','%'),'%') AND r.revision= versioncontrol_operations.revision)", 'matched_terms');
+  }
+  function render($values) {
+    $terms = explode(',', $values->matched_terms);
+    foreach ($terms as $k => $v)
+      $terms[$k] = taxonomy_get_term($v);
+    array_walk($terms, create_function('&$item', '$item=l($item->name,taxonomy_term_path($item));'));
+    return implode(', ', $terms);
+  }
+}
Index: includes/versioncontrol_views_handler_field_revision.inc
===================================================================
--- includes/versioncontrol_views_handler_field_revision.inc	(revision 0)
+++ includes/versioncontrol_views_handler_field_revision.inc	(revision 0)
@@ -0,0 +1,23 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Version Control API Views Handler: Field "Revision"
+ */
+
+class versioncontrol_views_handler_field_revision extends views_handler_field_numeric {
+  function render_link($data, $values) {
+    $title = 'r'. $data;
+    if (user_access('access commit messages')) {
+      return l($title, "commitlog", array('query' => array('id' => $values->vc_op_id)));
+    }
+    else {
+      return $title;
+    }
+  }
+
+  function render($values) {
+    return $this->render_link(check_plain($values->{$this->field_alias}), $values);
+  }
+}
Index: includes/versioncontrol.views.inc
===================================================================
--- includes/versioncontrol.views.inc	(revision 0)
+++ includes/versioncontrol.views.inc	(revision 0)
@@ -0,0 +1,240 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Views implementation for Version Control API
+ */
+
+function versioncontrol_views_data() {
+
+  // =========================================================================
+  // versioncontrol_operations
+
+  $data['versioncontrol_operations']['table']['group'] = t('Version Control');
+
+  $data['versioncontrol_operations']['table']['base'] = array(
+    'field' => 'vc_op_id',
+    'title' => t('Version Control Operations'),
+    'help' => t("Commits to all active repositories"),
+  );
+
+  $data['versioncontrol_operations']['message'] = array(
+    'title' => t('Message'),
+    'help' => t('The commit log message.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+  );
+  $data['versioncontrol_operations']['username'] = array(
+    'title' => t('VCS Username'),
+    'help' => t('The VCS username responsible for this commit.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+  );
+  $data['versioncontrol_operations']['date'] = array(
+    'title' => t('Date'),
+    'help' => t('The date this commit occurred.'),
+    'field' => array(
+      'handler' => 'views_handler_field_date',
+      'click sortable' => TRUE,
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort_date',
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_date',
+    ),
+  );
+  $data['versioncontrol_operations']['revision'] = array(
+    'title' => t('Revision'),
+    'help' => t('The revision number of this commit.'),
+    'field' => array(
+      'handler' => 'versioncontrol_views_handler_field_revision',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_numeric',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_numeric',
+    ),
+  );
+  if (module_exists('versioncontrol_svn')) {
+    /// @todo: currently this only works with the SVN backend, as it relies on versioncontrol_svn_repositories.path_trunk
+    $data['versioncontrol_operations']['path_terms'] = array(
+      'title' => t('Path Terms'),
+      'help' => t('Terms matching paths in this commit.'),
+      'field' => array(
+        'handler' => 'versioncontrol_views_handler_field_path_terms',
+      ),
+    );
+  }
+
+  // =========================================================================
+  // versioncontrol_repositories
+
+  $data['versioncontrol_repositories']['table']['group'] = t('Version Control');
+
+  $data['versioncontrol_repositories']['table']['join'] = array(
+    'versioncontrol_operations' => array(
+      'left_field' => 'repo_id',
+      'field' => 'repo_id',
+    ),
+  );
+
+  $data['versioncontrol_repositories']['name'] = array(
+    'title' => t('Repository'),
+    'help' => t('The name of the Version Control Repository in which this commit happened.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+  );
+
+  $data['versioncontrol_repositories']['vcs'] = array(
+    'title' => t('VCS'),
+    'help' => t('The name of the Version Control System used by the repository in which this commit happened.'),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'argument' => array(
+      'handler' => 'views_handler_argument_string',
+    ),
+  );
+
+  // =========================================================================
+  // versioncontrol_svn_repositories
+
+  $data['versioncontrol_svn_repositories']['table']['group'] = t('Version Control');
+
+  $data['versioncontrol_svn_repositories']['table']['join'] = array(
+    'versioncontrol_operations' => array(
+      'left_field' => 'repo_id',
+      'field' => 'repo_id',
+    ),
+  );
+
+  // =========================================================================
+  // versioncontrol_accounts
+
+  $data['versioncontrol_accounts']['table']['group'] = t('Version Control');
+
+  $data['versioncontrol_accounts']['table']['join'] = array(
+    'versioncontrol_operations' => array(
+      'left_field' => 'username',
+      'field' => 'username',
+      'extra' => 'versioncontrol_operations.repo_id = versioncontrol_accounts.repo_id',
+    ),
+  );
+
+  $data['versioncontrol_accounts']['uid'] = array(
+    'title' => t('User'),
+    'help' => t("The User matching the commit's author."),
+    'relationship' => array(
+      'base' => 'users',
+      'field' => 'uid',
+      'handler' => 'views_handler_relationship',
+      'label' => t('User'),
+    ),
+  );
+
+  // =========================================================================
+  // versioncontrol_item_revisions
+
+  $data['versioncontrol_item_revisions']['table']['group'] = t('Version Control');
+
+  $data['versioncontrol_item_revisions']['table']['join'] = array(
+    'versioncontrol_operations' => array(
+      'left_field' => 'revision',
+      'field' => 'revision',
+      'extra' => 'versioncontrol_operations.repo_id = versioncontrol_item_revisions.repo_id',
+    ),
+  );
+
+  $data['versioncontrol_item_revisions']['path'] = array(
+    'title' => t('Paths'),
+    'help' => t("Paths involved in this commit.  Warning: this will produce a views row for every path involved in every commit, so you may need to do some additional filtering."),
+    'relationship' => array(
+      'base' => 'versioncontrol_operations',
+      'field' => 'item_revision_id',
+      'handler' => 'views_handler_relationship',
+      'label' => t('Path'),
+    ),
+    'field' => array(
+      'handler' => 'views_handler_field',
+      'click sortable' => TRUE,
+    ),
+    'filter' => array(
+      'handler' => 'views_handler_filter_string',
+    ),
+    'sort' => array(
+      'handler' => 'views_handler_sort',
+    ),
+    'argument' => array(
+      'handler' => 'versioncontrol_views_handler_argument_path_terms',
+    ),
+  );
+
+  return $data;
+}
+
+
+function versioncontrol_views_handlers() {
+  return array(
+    'info' => array(
+      'path' => drupal_get_path('module', 'versioncontrol') .'/includes',
+    ),
+    'handlers' => array(
+      'versioncontrol_views_handler_field_path_terms' => array(
+        'parent' => 'views_handler_field',
+      ),
+      'versioncontrol_views_handler_argument_path_terms' => array(
+        'parent' => 'views_handler_argument_term_node_tid',
+      ),
+      'versioncontrol_views_handler_field_revision' => array(
+        'parent' => 'views_handler_field_numeric',
+      ),
+    ),
+  );
+}
Index: versioncontrol.module
===================================================================
--- versioncontrol.module	(revision 5058)
+++ versioncontrol.module	(working copy)
@@ -67,6 +67,7 @@
 function versioncontrol_init() {
   // The backend-only part of the API.
   module_load_include('inc', 'versioncontrol', 'versioncontrol-backend');
+  module_load_include('inc', 'versioncontrol', 'includes/versioncontrol.views');
 }
 
 /**
