You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2014/02/06 00:44:47 UTC

svn commit: r1564998 - in /subversion/branches/automatic-pager/subversion/svn: blame-cmd.c cl.h diff-cmd.c help-cmd.c util.c

Author: breser
Date: Wed Feb  5 23:44:46 2014
New Revision: 1564998

URL: http://svn.apache.org/r1564998
Log:
Initial and very rough support for automatic pager for the blame, diff and help
commands.

* subversion/svn/util.c
  (): pull in necessary headers.
  (svn_cl__start_pager, svn_cl__close_pager): New

* subversion/svn/cl.h
  (svn_cl__start_pager, svn_cl__close_pager): New

* subversion/svn/blame-cmd.c
  (svn_cl__blame): Add support for automatic pager.

* subversion/svn/diff-cmd.c
  (svn_cl__diff): Add support for automatic pager.

* subversion/svn/help-cmd.c
  (svn_cl__help): Add support for automatic pager.

Patch by: stsp
(from https://mail-archives.apache.org/mod_mbox/subversion-dev/201402.mbox/%3C20140203200233.GA29698%40jim.stsp.name%3E with changelog by me)

Modified:
    subversion/branches/automatic-pager/subversion/svn/blame-cmd.c
    subversion/branches/automatic-pager/subversion/svn/cl.h
    subversion/branches/automatic-pager/subversion/svn/diff-cmd.c
    subversion/branches/automatic-pager/subversion/svn/help-cmd.c
    subversion/branches/automatic-pager/subversion/svn/util.c

Modified: subversion/branches/automatic-pager/subversion/svn/blame-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/automatic-pager/subversion/svn/blame-cmd.c?rev=1564998&r1=1564997&r2=1564998&view=diff
==============================================================================
--- subversion/branches/automatic-pager/subversion/svn/blame-cmd.c (original)
+++ subversion/branches/automatic-pager/subversion/svn/blame-cmd.c Wed Feb  5 23:44:46 2014
@@ -246,6 +246,7 @@ svn_cl__blame(apr_getopt_t *os,
   svn_boolean_t end_revision_unspecified = FALSE;
   svn_diff_file_options_t *diff_options = svn_diff_file_options_create(pool);
   svn_boolean_t seen_nonexistent_target = FALSE;
+  apr_proc_t *pager_proc = NULL;
 
   SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                       opt_state->targets,
@@ -316,6 +317,9 @@ svn_cl__blame(apr_getopt_t *os,
                                   "mode"));
     }
 
+  if (!opt_state->non_interactive && !opt_state->xml)
+    SVN_ERR(svn_cl__start_pager(&pager_proc, pool, pool));
+
   for (i = 0; i < targets->nelts; i++)
     {
       svn_error_t *err;
@@ -409,6 +413,9 @@ svn_cl__blame(apr_getopt_t *os,
   if (opt_state->xml && ! opt_state->incremental)
     SVN_ERR(svn_cl__xml_print_footer("blame", pool));
 
+  if (pager_proc)
+    SVN_ERR(svn_cl__close_pager(pager_proc, pool));
+
   if (seen_nonexistent_target)
     return svn_error_create(
       SVN_ERR_ILLEGAL_TARGET, NULL,

Modified: subversion/branches/automatic-pager/subversion/svn/cl.h
URL: http://svn.apache.org/viewvc/subversion/branches/automatic-pager/subversion/svn/cl.h?rev=1564998&r1=1564997&r2=1564998&view=diff
==============================================================================
--- subversion/branches/automatic-pager/subversion/svn/cl.h (original)
+++ subversion/branches/automatic-pager/subversion/svn/cl.h Wed Feb  5 23:44:46 2014
@@ -848,6 +848,22 @@ svn_cl__deprecated_merge_reintegrate(con
                                      svn_client_ctx_t *ctx,
                                      apr_pool_t *pool);
 
+
+/* Launch an external pager program and redirect stdout to the pager.
+ *
+ * If the pager was started, return a pointer to the process handle
+ * for the pager in *PAGER_PROC. Else, set *PAGER_PROC to NULL. */
+svn_error_t *
+svn_cl__start_pager(apr_proc_t **pager_proc,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool);
+
+/* Close the pager with process handle PAGER_PROC.
+ * Must be called after all output has been written. */
+svn_error_t *
+svn_cl__close_pager(apr_proc_t *pager_proc,
+                    apr_pool_t *scratch_pool);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/automatic-pager/subversion/svn/diff-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/automatic-pager/subversion/svn/diff-cmd.c?rev=1564998&r1=1564997&r2=1564998&view=diff
==============================================================================
--- subversion/branches/automatic-pager/subversion/svn/diff-cmd.c (original)
+++ subversion/branches/automatic-pager/subversion/svn/diff-cmd.c Wed Feb  5 23:44:46 2014
@@ -188,6 +188,7 @@ svn_cl__diff(apr_getopt_t *os,
   struct summarize_baton_t summarize_baton;
   const svn_client_diff_summarize_func_t summarize_func =
     (opt_state->xml ? summarize_xml : summarize_regular);
+  apr_proc_t *pager_proc = NULL;
 
   if (opt_state->extensions)
     options = svn_cstring_split(opt_state->extensions, " \t\n\r", TRUE, pool);
@@ -355,6 +356,9 @@ svn_cl__diff(apr_getopt_t *os,
 
   svn_opt_push_implicit_dot_target(targets, pool);
 
+  if (!opt_state->non_interactive && !opt_state->diff.summarize)
+    SVN_ERR(svn_cl__start_pager(&pager_proc, pool, pool));
+
   iterpool = svn_pool_create(pool);
 
   for (i = 0; i < targets->nelts; ++i)
@@ -488,5 +492,8 @@ svn_cl__diff(apr_getopt_t *os,
 
   svn_pool_destroy(iterpool);
 
+  if (pager_proc)
+    SVN_ERR(svn_cl__close_pager(pager_proc, pool));
+
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/automatic-pager/subversion/svn/help-cmd.c
URL: http://svn.apache.org/viewvc/subversion/branches/automatic-pager/subversion/svn/help-cmd.c?rev=1564998&r1=1564997&r2=1564998&view=diff
==============================================================================
--- subversion/branches/automatic-pager/subversion/svn/help-cmd.c (original)
+++ subversion/branches/automatic-pager/subversion/svn/help-cmd.c Wed Feb  5 23:44:46 2014
@@ -45,6 +45,7 @@ svn_cl__help(apr_getopt_t *os,
 {
   svn_cl__opt_state_t *opt_state = NULL;
   svn_stringbuf_t *version_footer = NULL;
+  apr_proc_t *pager_proc = NULL;
 
   char help_header[] =
   N_("usage: svn <subcommand> [options] [args]\n"
@@ -132,16 +133,24 @@ svn_cl__help(apr_getopt_t *os,
     version_footer = svn_stringbuf_create(ra_desc_start, pool);
   SVN_ERR(svn_ra_print_modules(version_footer, pool));
 
-  return svn_opt_print_help4(os,
-                             "svn",   /* ### erm, derive somehow? */
-                             opt_state ? opt_state->version : FALSE,
-                             opt_state ? opt_state->quiet : FALSE,
-                             opt_state ? opt_state->verbose : FALSE,
-                             version_footer->data,
-                             help_header,   /* already gettext()'d */
-                             svn_cl__cmd_table,
-                             svn_cl__options,
-                             svn_cl__global_options,
-                             _(help_footer),
-                             pool);
+  if (!opt_state->non_interactive)
+    SVN_ERR(svn_cl__start_pager(&pager_proc, pool, pool));
+
+  SVN_ERR(svn_opt_print_help4(os,
+                              "svn",   /* ### erm, derive somehow? */
+                              opt_state ? opt_state->version : FALSE,
+                              opt_state ? opt_state->quiet : FALSE,
+                              opt_state ? opt_state->verbose : FALSE,
+                              version_footer->data,
+                              help_header,   /* already gettext()'d */
+                              svn_cl__cmd_table,
+                              svn_cl__options,
+                              svn_cl__global_options,
+                              _(help_footer),
+                              pool));
+
+  if (pager_proc)
+    SVN_ERR(svn_cl__close_pager(pager_proc, pool));
+
+  return SVN_NO_ERROR;
 }

Modified: subversion/branches/automatic-pager/subversion/svn/util.c
URL: http://svn.apache.org/viewvc/subversion/branches/automatic-pager/subversion/svn/util.c?rev=1564998&r1=1564997&r2=1564998&view=diff
==============================================================================
--- subversion/branches/automatic-pager/subversion/svn/util.c (original)
+++ subversion/branches/automatic-pager/subversion/svn/util.c Wed Feb  5 23:44:46 2014
@@ -33,6 +33,15 @@
 #include <ctype.h>
 #include <assert.h>
 
+#ifndef WIN32
+#include <unistd.h>
+#else
+#include <crtdbg.h>
+#include <io.h>
+#include <conio.h>
+#endif
+
+#include <apr.h>                /* for STDOUT_FILENO */
 #include <apr_env.h>
 #include <apr_errno.h>
 #include <apr_file_info.h>
@@ -1062,3 +1071,86 @@ svn_cl__propset_print_binary_mime_type_w
   return SVN_NO_ERROR;
 }
 
+svn_error_t *
+svn_cl__start_pager(apr_proc_t **pager_proc,
+                    apr_pool_t *result_pool,
+                    apr_pool_t *scratch_pool)
+{
+  apr_array_header_t *pager_cmd;
+  const char *pager;
+  const char **args;
+  apr_file_t *stdout_file;
+  apr_status_t apr_err;
+  int i;
+
+  *pager_proc = NULL;
+
+  pager = getenv("SVN_PAGER");
+  if (pager == NULL)
+    pager = getenv("PAGER");
+  /* TODO get pager-cmd from config */
+  if (pager == NULL)
+    return SVN_NO_ERROR;
+
+#ifdef WIN32
+  if (_isatty(STDOUT_FILENO) == 0)
+    return SVN_NO_ERROR;
+#else
+  if (isatty(STDOUT_FILENO) == 0)
+    return SVN_NO_ERROR;
+#endif
+
+  pager_cmd = svn_cstring_split(pager, " \t", TRUE, scratch_pool);
+  if (pager_cmd->nelts <= 0)
+    return SVN_NO_ERROR;
+  args = apr_pcalloc(scratch_pool,
+                     (sizeof(const char *) * pager_cmd->nelts + 1));
+  for (i = 0; i < pager_cmd->nelts; i++)
+    args[i] = APR_ARRAY_IDX(pager_cmd, i, const char *);
+  args[i] = NULL;
+
+  apr_err = apr_file_open_stdout(&stdout_file, scratch_pool);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, "Can't open stdout");
+
+  *pager_proc = apr_pcalloc(result_pool, sizeof(**pager_proc));
+  SVN_ERR(svn_io_start_cmd3(*pager_proc, NULL, args[0], args, NULL, TRUE,
+                            TRUE, NULL,
+                            FALSE, NULL,
+                            FALSE, NULL,
+                            result_pool));
+
+  apr_err = apr_file_dup2(stdout_file, (*pager_proc)->in, result_pool);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, "Can't redirect stdout");
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_cl__close_pager(apr_proc_t *pager_proc,
+                    apr_pool_t *scratch_pool)
+{
+  apr_file_t *stdout_file;
+  apr_status_t apr_err;
+  svn_error_t *err;
+
+  apr_err = apr_file_open_stdout(&stdout_file, scratch_pool);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, "Can't open stdout");
+  SVN_ERR(svn_io_file_close(stdout_file, scratch_pool));
+  SVN_ERR(svn_io_file_close(pager_proc->in, scratch_pool));
+  err = svn_io_wait_for_cmd(pager_proc,
+                            apr_psprintf(scratch_pool, "%ld",
+                                         (long)pager_proc->pid),
+                            NULL, NULL, scratch_pool);
+  if (err && err->apr_err == SVN_ERR_EXTERNAL_PROGRAM)
+    {
+      svn_handle_warning2(stderr, err, "svn: ");
+      svn_error_clear(err);
+    }
+  else
+    SVN_ERR(err);
+
+  return SVN_NO_ERROR;
+}