Index: subversion/include/svn_opt.h
===================================================================
--- subversion/include/svn_opt.h	(revision 13420)
+++ subversion/include/svn_opt.h	(working copy)
@@ -215,19 +215,27 @@
 
 /**
  * Set @a *start_revision and/or @a *end_revision according to @a arg, 
- * where @a arg is "N" or "N:M", like so:
+ * where @a arg is "N", "N:M", "N:", ":M" or ":", like so:
  * 
  *    - If @a arg is "N", set @a *start_revision to represent N, and
  *      leave @a *end_revision untouched.
  *
  *    - If @a arg is "N:M", set @a *start_revision and @a *end_revision
  *      to represent N and M respectively. 
- * 
+ *
+ *    - If @a arg is "N:", set @a *start_revision to represent N, and
+ *      set @a *end_revision to HEAD.
+ *
+ *    - If @a arg is ":M", set @a *start_revision to r0, and set
+ *      @a *end_revision to represent M.
+ *
+ *    - If @a arg is ":", set @a *start_revision to r0, and set
+ *      @a *end_revision to HEAD.
+ *
  * N and/or M may be one of the special revision descriptors
  * recognized by @c revision_from_word(), or a date in curly braces.
  *
  * If @a arg is invalid, return -1; else return 0.
- * It is invalid to omit a revision (as in, ":", "N:" or ":M").
  *
  * Note:
  *
Index: subversion/libsvn_subr/opt.c
===================================================================
--- subversion/libsvn_subr/opt.c	(revision 13420)
+++ subversion/libsvn_subr/opt.c	(working copy)
@@ -345,6 +345,24 @@
       revision->value.date = tm;
       return end + 1;
     }
+  else if (*str == ':')
+    {
+      /* Colon means either "earliest" or HEAD depending on context. */
+      end = str + 1;
+      if (*end == '\0')
+	{
+	    revision->kind = svn_opt_revision_head;
+	}
+      else
+	{
+	  /* Pick earliest revision of target (r0 should do the trick,
+	     but are we paying a penalty for not finding the *exact*
+	     earliest revision?). */
+	  revision->kind = svn_opt_revision_number;
+	  revision->value.number = 0;
+	}
+      return end;
+    }
   else if (apr_isdigit (*str))
     {
       /* It's a number. */
@@ -383,18 +401,30 @@
 {
   char *left_rev, *right_rev, *end;
 
+  /* Handle special case where arg is ":". */
+  if (strcmp(arg, ":") == 0)
+    {
+      start_revision->kind = svn_opt_revision_number;
+      start_revision->value.number = 0;
+      end_revision->kind = svn_opt_revision_head;
+      return 0;
+    }
+
   /* Operate on a copy of the argument. */
   left_rev = apr_pstrdup (pool, arg);
 
   right_rev = parse_one_rev (start_revision, left_rev, pool);
-  if (right_rev && *right_rev == ':')
+  if (right_rev && *right_rev != '\0')
     {
-      right_rev++;
+      /* If right_rev is ":M", then we need to increment it, otherwise,
+	 we need to leave it be. */
+      if (*right_rev == ':' && *(right_rev + 1) != '\0')
+        right_rev++;
       end = parse_one_rev (end_revision, right_rev, pool);
       if (!end || *end != '\0')
         return -1;
     }
-  else if (!right_rev || *right_rev != '\0')
+  else if (!right_rev)
     return -1;
 
   return 0;


