Author: brane
Date: Sun Nov 25 23:22:20 2018
New Revision: 1847443

URL: http://svn.apache.org/viewvc?rev=1847443&view=rev
Log:
Teach 'svn info' to show human-readable file sizes.

* subversion/svn/cl.h (svn_cl__get_base2_unit_file_size): New prototype.

* subversion/svn/filesize.c: New file.
  (svn_cl__get_base2_unit_file_size): Implement. Moved here from list-cmd.c.

* subversion/svn/list-cmd.c: Remove unused includes.
  (get_human_readable_size): Remove. Implementation moved to filesize.c.
  (print_dirent): Use svn_cl__get_base2_unit_file_size().

* subversion/svn/info-cmd.c
  (print_info_baton_t): New member 'human_readable'.
  (print_info): Optionally print human-readable file sizes.
  (svn_cl__info): Handle option --human-readable.

* subversion/svn/svn.c (svn_cl__cmd_table): Add -H to 'svn info'.

Added:
    subversion/trunk/subversion/svn/filesize.c   (with props)
Modified:
    subversion/trunk/subversion/svn/cl.h
    subversion/trunk/subversion/svn/info-cmd.c
    subversion/trunk/subversion/svn/list-cmd.c
    subversion/trunk/subversion/svn/svn.c

Modified: subversion/trunk/subversion/svn/cl.h
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/cl.h?rev=1847443&r1=1847442&r2=1847443&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/cl.h (original)
+++ subversion/trunk/subversion/svn/cl.h Sun Nov 25 23:22:20 2018
@@ -32,6 +32,7 @@
 #include <apr_tables.h>
 #include <apr_getopt.h>
 
+#include "svn_types.h"
 #include "svn_wc.h"
 #include "svn_client.h"
 #include "svn_string.h"
@@ -722,6 +723,16 @@ svn_cl__node_kind_str_xml(svn_node_kind_
 const char *
 svn_cl__node_kind_str_human_readable(svn_node_kind_t kind);
 
+/* Return the size of a file, formatted to 3 colums in base-2 units.
+   if LONG_UNITS is TRUE, unit suffixes will be the whole SI symbol,
+   e.g., KiB, MiB, etc; otherwise only the first letters will be used.
+
+   File sizes are never negative, so we don't handle that case other than
+   making sure that the scale adjustment will work. */
+const char *
+svn_cl__get_base2_unit_file_size(svn_filesize_t size,
+                                 svn_boolean_t long_units,
+                                 apr_pool_t *result_pool);
 
 /** Provides an XML name for a given OPERATION.
  * Note: POOL is currently not used.

Added: subversion/trunk/subversion/svn/filesize.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/filesize.c?rev=1847443&view=auto
==============================================================================
--- subversion/trunk/subversion/svn/filesize.c (added)
+++ subversion/trunk/subversion/svn/filesize.c Sun Nov 25 23:22:20 2018
@@ -0,0 +1,118 @@
+/*
+ * filesize.c -- Utilities for displaying file sizes
+ *
+ * ====================================================================
+ *    Licensed to the Apache Software Foundation (ASF) under one
+ *    or more contributor license agreements.  See the NOTICE file
+ *    distributed with this work for additional information
+ *    regarding copyright ownership.  The ASF licenses this file
+ *    to you under the Apache License, Version 2.0 (the
+ *    "License"); you may not use this file except in compliance
+ *    with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing,
+ *    software distributed under the License is distributed on an
+ *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *    KIND, either express or implied.  See the License for the
+ *    specific language governing permissions and limitations
+ *    under the License.
+ * ====================================================================
+ */
+
+
+/*** Includes. ***/
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+
+#include <apr_strings.h>
+
+#include "cl.h"
+
+
+/*** Code. ***/
+
+const char *
+svn_cl__get_base2_unit_file_size(svn_filesize_t size,
+                                 svn_boolean_t long_units,
+                                 apr_pool_t *result_pool)
+{
+  static const struct
+  {
+    svn_filesize_t mask;
+    const char *suffix;
+    const char *short_suffix;
+  }
+  order[] =
+    {
+      {APR_INT64_C(0x0000000000000000), " B",   "B"}, /* byte */
+      {APR_INT64_C(0x00000000000003FF), " KiB", "K"}, /* kibi */
+      {APR_INT64_C(0x00000000000FFFFF), " MiB", "M"}, /* mibi */
+      {APR_INT64_C(0x000000003FFFFFFF), " GiB", "G"}, /* gibi */
+      {APR_INT64_C(0x000000FFFFFFFFFF), " TiB", "T"}, /* tibi */
+      {APR_INT64_C(0x0003FFFFFFFFFFFF), " EiB", "E"}, /* exbi */
+      {APR_INT64_C(0x0FFFFFFFFFFFFFFF), " PiB", "P"}  /* pibi */
+    };
+  static const apr_size_t order_size = sizeof(order) / sizeof(order[0]);
+
+  const svn_filesize_t abs_size = ((size < 0) ? -size : size);
+  double human_readable_size;
+
+  /* Find the size mask for the (absolute) file size. It would be sexy to
+     do a binary search here, but with only 7 elements in the array ... */
+  apr_size_t index = order_size;
+  while (index > 0)
+    {
+      --index;
+      if (abs_size > order[index].mask)
+        break;
+    }
+
+  /* Adjust the size to the given order of magnitude.
+
+     This is division by (order[index].mask + 1), which is the base-2^10
+     magnitude of the size; and that is the same as an arithmetic right
+     shift by (index * 10) bits. But we split it into an integer and a
+     floating-point division, so that we don't overflow the mantissa at
+     very large file sizes. */
+  ;
+  if ((abs_size >> 10 * index) > 999)
+    {
+      /* This assertion should never fail, because we only have 4 binary
+         digits in the petabyte range and so the number of petabytes can't
+         be large enough to enter this conditional block. */
+      assert(index < order_size - 1);
+      ++index;
+    }
+  human_readable_size = (index == 0 ? (double)size
+                         : (size >> 3 * index) / 128.0 / index);
+
+  /* NOTE: We want to display a locale-specific decimal sepratator, but
+           APR's formatter completely ignores the locale. So we use the
+           good, old, standard, *dangerous* sprintf() to format the size.
+
+           But, on the brigt side, we've just made sure that the number has
+           no more than 3 non-fractional digits. So the call to sprintf()
+           here should be safe. */
+  {
+    const char *const suffix = (long_units ? order[index].suffix
+                                : order[index].short_suffix);
+
+    /*   3 digits (or 2 digits and 1 decimal separator)
+       + 1 negative sign (which should not appear under normal circumstances)
+       + 1 nul terminator
+       ---
+       = 5 characters of space needed in the buffer. */
+    char buffer[8];
+
+    /* When the adjusted size has only one significant digit left of the
+       decimal point, show tenths of a unit, too. */
+    sprintf(buffer, "%.*f",
+            fabs(human_readable_size) < 10.0 ? 1 : 0,
+            human_readable_size);
+    return apr_pstrcat(result_pool, buffer, suffix, SVN_VA_NULL);
+  }
+}

Propchange: subversion/trunk/subversion/svn/filesize.c
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: subversion/trunk/subversion/svn/info-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/info-cmd.c?rev=1847443&r1=1847442&r2=1847443&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/info-cmd.c (original)
+++ subversion/trunk/subversion/svn/info-cmd.c Sun Nov 25 23:22:20 2018
@@ -421,6 +421,9 @@ typedef struct print_info_baton_t
   /* Did we already print a line of output? */
   svn_boolean_t start_new_line;
 
+  /* Are we going to print human-readable sizes? */
+  svn_boolean_t human_readable;
+
   /* The client context. */
   svn_client_ctx_t *ctx;
 } print_info_baton_t;
@@ -763,9 +766,15 @@ print_info(void *baton,
     }
 
   if (info->kind == svn_node_file && info->size != SVN_INVALID_FILESIZE)
-    SVN_ERR(svn_cmdline_printf(pool, _("Size in Repository: %s\n"),
-                               apr_psprintf(pool, "%" SVN_FILESIZE_T_FMT,
-                                            info->size)));
+    {
+      const char *const sizestr =
+        (receiver_baton->human_readable
+         ? svn_cl__get_base2_unit_file_size(info->size, TRUE, pool)
+         : apr_psprintf(pool, "%" SVN_FILESIZE_T_FMT,
+                        info->size));
+      SVN_ERR(svn_cmdline_printf(pool, _("Size in Repository: %s\n"),
+                                 sizestr));
+    }
 
   if (info->wc_info)
     {
@@ -1262,6 +1271,10 @@ svn_cl__info(apr_getopt_t *os,
         return svn_error_create(
             SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
             _("--no-newline is not valid in --xml mode"));
+      if (opt_state->human_readable)
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--human-readable is not valid in --xml mode"));
 
       /* If output is not incremental, output the XML header and wrap
          everything in a top-level element. This makes the output in
@@ -1277,6 +1290,10 @@ svn_cl__info(apr_getopt_t *os,
         return svn_error_create(
             SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
             _("--incremental is only valid in --xml mode"));
+      if (opt_state->human_readable)
+        return svn_error_create(
+            SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+            _("--human-readable is not valid with --show-item"));
 
       receiver_baton.multiple_targets = (opt_state->depth > svn_depth_empty
                                          || targets->nelts > 1);
@@ -1292,6 +1309,7 @@ svn_cl__info(apr_getopt_t *os,
   else
     {
       receiver = print_info;
+      receiver_baton.human_readable = opt_state->human_readable;
 
       if (opt_state->incremental)
         return svn_error_create(

Modified: subversion/trunk/subversion/svn/list-cmd.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/list-cmd.c?rev=1847443&r1=1847442&r2=1847443&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/list-cmd.c (original)
+++ subversion/trunk/subversion/svn/list-cmd.c Sun Nov 25 23:22:20 2018
@@ -21,10 +21,6 @@
  * ====================================================================
  */
 
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
-
 #include "svn_cmdline.h"
 #include "svn_client.h"
 #include "svn_error.h"
@@ -74,85 +70,6 @@ static const apr_uint32_t print_dirent_f
     SVN_DIRENT_KIND  | SVN_DIRENT_SIZE | SVN_DIRENT_TIME |
     SVN_DIRENT_CREATED_REV | SVN_DIRENT_LAST_AUTHOR);
 
-/* Converts a file size to human-readable form with base-2 unit suffix.
-   File sizes are never negative, so we don't handle that case other than
-   making sure that the scale adjustment will work. */
-static const char *
-get_human_readable_size(svn_filesize_t size, apr_pool_t *scratch_pool)
-{
-  static const struct
-  {
-    svn_filesize_t mask;
-    char suffix;
-  }
-  order[] =
-    {
-      {APR_INT64_C(0x0000000000000000), 'B'}, /* byte */
-      {APR_INT64_C(0x00000000000003FF), 'K'}, /* kibi */
-      {APR_INT64_C(0x00000000000FFFFF), 'M'}, /* mibi */
-      {APR_INT64_C(0x000000003FFFFFFF), 'G'}, /* gibi */
-      {APR_INT64_C(0x000000FFFFFFFFFF), 'T'}, /* tibi */
-      {APR_INT64_C(0x0003FFFFFFFFFFFF), 'E'}, /* exbi */
-      {APR_INT64_C(0x0FFFFFFFFFFFFFFF), 'P'}  /* pibi */
-    };
-  static const apr_size_t order_size = sizeof(order) / sizeof(order[0]);
-
-  const svn_filesize_t abs_size = ((size < 0) ? -size : size);
-  double human_readable_size;
-
-  /* Find the size mask for the (absolute) file size. It would be sexy to
-     do a binary search here, but with only 7 elements in the array ... */
-  apr_size_t index = order_size;
-  while (index > 0)
-    {
-      --index;
-      if (abs_size > order[index].mask)
-        break;
-    }
-
-  /* Adjust the size to the given order of magnitude.
-
-     This is division by (order[index].mask + 1), which is the base-2^10
-     magnitude of the size; and that is the same as an arithmetic right
-     shift by (index * 10) bits. But we split it into an integer and a
-     floating-point division, so that we don't overflow the mantissa at
-     very large file sizes. */
-  ;
-  if ((abs_size >> 10 * index) > 999)
-    {
-      /* This assertion should never fail, because we only have 4 binary
-         digits in the petabyte range and so the number of petabytes can't
-         be large enough to enter this conditional block. */
-      assert(index < order_size - 1);
-      ++index;
-    }
-  human_readable_size = (index == 0 ? (double)size
-                         : (size >> 3 * index) / 128.0 / index);
-
-  /* NOTE: We want to display a locale-specific decimal sepratator, but
-           APR's formatter completely ignores the locale. So we use the
-           good, old, standard, *dangerous* sprintf() to format the size.
-
-           But, on the brigt side, we've just made sure that the number has
-           no more than 3 non-fractional digits. So the call to sprintf()
-           here should be safe. */
-  {
-    /*   3 digits (or 2 digits and 1 decimal separator)
-       + 1 unit suffix
-       + 1 negative sign (which should not appear under normal circumstances)
-       + 1 nul terminator
-       ---
-       = 6 characters of space needed in the buffer. */
-    char buffer[8];
-
-    /* When the adjusted size has only one significant digit left of the
-       decimal point, show tenths of a unit, too. */
-    sprintf(buffer, "%.*f%c",
-            fabs(human_readable_size) < 10.0 ? 1 : 0,
-            human_readable_size, order[index].suffix);
-    return apr_pstrdup(scratch_pool, buffer);
-  }
-}
 
 /* This implements the svn_client_list_func2_t API, printing a single
    directory entry in text format. */
@@ -265,7 +182,8 @@ print_dirent(void *baton,
       if (dirent->kind == svn_node_file)
         {
           if (pb->human_readable)
-            sizestr = get_human_readable_size(dirent->size, scratch_pool);
+            sizestr = svn_cl__get_base2_unit_file_size(dirent->size, FALSE,
+                                                       scratch_pool);
           else
             sizestr = apr_psprintf(scratch_pool, "%" SVN_FILESIZE_T_FMT,
                                    dirent->size);

Modified: subversion/trunk/subversion/svn/svn.c
URL: 
http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/svn.c?rev=1847443&r1=1847442&r2=1847443&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/svn.c (original)
+++ subversion/trunk/subversion/svn/svn.c Sun Nov 25 23:22:20 2018
@@ -859,9 +859,16 @@ const svn_opt_subcommand_desc3_t svn_cl_
      "  EXPERIMENTAL:\n"
      "  With --x-viewspec, print the working copy layout.\n"
     )},
-    {'r', 'R', opt_depth, opt_targets, opt_incremental, opt_xml,
+    {'r', 'R', 'H', opt_depth, opt_targets, opt_incremental, opt_xml,
      opt_changelist, opt_include_externals, opt_show_item, opt_no_newline,
-     opt_viewspec}
+     opt_viewspec},
+    {{'H', N_("show file sizes with base-2 unit suffixes\n"
+              "                             "
+              "(Byte, Kilobyte, Megabyte, Gigabyte, Terabyte\n"
+              "                             "
+              "and Petabyte), limiting the number of digits\n"
+              "                             "
+              "to three or less")}}
   },
 
   { "list", svn_cl__list, {"ls"},


Reply via email to