You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by ju...@apache.org on 2015/11/16 18:46:38 UTC

svn commit: r1714640 - in /subversion/trunk: ./ notes/move-tracking/ subversion/include/private/ subversion/libsvn_delta/ subversion/libsvn_fs_x/ subversion/libsvn_subr/ subversion/tests/cmdline/ subversion/tests/cmdline/svntest/ tools/dev/svnmover/

Author: julianfoad
Date: Mon Nov 16 17:46:37 2015
New Revision: 1714640

URL: http://svn.apache.org/viewvc?rev=1714640&view=rev
Log:
Merge the 'svnmover' prototype from the 'move-tracking-2' branch to trunk.

See the dev@ email thread "Merge 'svnmover' demo tool to trunk" started on
2015-11-10, archived at e.g. <http://mail-archives.apache.org/mod_mbox/subversion-dev/201511.mbox/%3CCAEcU=1YE5Ci02j_4aAeB_roS1X0H2QWPP3juu0exjVJ-FGCLyg@mail.gmail.com%3E>.

This is a reintegration (performed as an automatic merge) followed by
reverting the unwanted parts. As such, those unwanted parts (such as shim
insertions in several libraries) will be treated as 'record-only merged' and
will not be picked up by any subsequent automatic merge to trunk.

A brief description of the changes follows.

* build.conf
  Adjust to build the new files.

* configure.ac
  Adjust compiler warning flags to not warn about passing or returning a
  structure, because some of the code does so.

* LICENSE
  Add the licence text for the embedded 'linenoise' library.

* notes/move-tracking/README
  New file, describing this work.

* subversion/include/private/svn_branch.h,
  subversion/include/private/svn_branch_compat.h,
  subversion/include/private/svn_branch_impl.h,
  subversion/include/private/svn_branch_nested.h,
  subversion/include/private/svn_branch_repos.h,
  subversion/include/private/svn_element.h
  New files.

* subversion/libsvn_delta/branch.c,
  subversion/libsvn_delta/branch_compat.c,
  subversion/libsvn_delta/branch_migrate.c,
  subversion/libsvn_delta/branch_nested.c,
  subversion/libsvn_delta/branch_repos.c,
  subversion/libsvn_delta/element.c
  New files.

* subversion/include/private/svn_cmdline_private.h
  subversion/libsvn_subr/cmdline.c
  (svn_cmdline__stdin_is_a_terminal,
   svn_cmdline__stdout_is_a_terminal,
   svn_cmdline__stderr_is_a_terminal): New.

* subversion/tests/cmdline/svnmover_tests.py
  New file.

* subversion/tests/cmdline/svntest/actions.py
  (run_and_verify_svnmover,
   run_and_verify_svnmover2): New.

* subversion/tests/cmdline/svntest/main.py
  (svnmover_binary,
   run_svnmover): New.
  (execute_tests): Initialize 'svnmover_binary'.

* subversion/tests/cmdline/svntest/wc.py
  (State): Add 'rename' and 'from_eids' methods.
  (StateItem): Add an 'eid' attribute.

* tools/dev/svnmover
  New tool.

Added:
    subversion/trunk/notes/move-tracking/
      - copied from r1714632, subversion/branches/move-tracking-2/notes/move-tracking/
    subversion/trunk/subversion/include/private/svn_branch.h
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/include/private/svn_branch.h
    subversion/trunk/subversion/include/private/svn_branch_compat.h
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/include/private/svn_branch_compat.h
    subversion/trunk/subversion/include/private/svn_branch_impl.h
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/include/private/svn_branch_impl.h
    subversion/trunk/subversion/include/private/svn_branch_nested.h
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/include/private/svn_branch_nested.h
    subversion/trunk/subversion/include/private/svn_branch_repos.h
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/include/private/svn_branch_repos.h
    subversion/trunk/subversion/include/private/svn_element.h
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/include/private/svn_element.h
    subversion/trunk/subversion/libsvn_delta/branch.c
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/libsvn_delta/branch.c
    subversion/trunk/subversion/libsvn_delta/branch_compat.c
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_compat.c
    subversion/trunk/subversion/libsvn_delta/branch_migrate.c
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_migrate.c
    subversion/trunk/subversion/libsvn_delta/branch_nested.c
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_nested.c
    subversion/trunk/subversion/libsvn_delta/branch_repos.c
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/libsvn_delta/branch_repos.c
    subversion/trunk/subversion/libsvn_delta/element.c
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/libsvn_delta/element.c
    subversion/trunk/subversion/tests/cmdline/svnmover_tests.py
      - copied unchanged from r1714632, subversion/branches/move-tracking-2/subversion/tests/cmdline/svnmover_tests.py
    subversion/trunk/tools/dev/svnmover/
      - copied from r1714632, subversion/branches/move-tracking-2/tools/dev/svnmover/
Modified:
    subversion/trunk/   (props changed)
    subversion/trunk/LICENSE
    subversion/trunk/build.conf
    subversion/trunk/configure.ac
    subversion/trunk/notes/move-tracking/README   (props changed)
    subversion/trunk/subversion/include/private/svn_cmdline_private.h
    subversion/trunk/subversion/libsvn_fs_x/   (props changed)
    subversion/trunk/subversion/libsvn_subr/cmdline.c
    subversion/trunk/subversion/tests/cmdline/svntest/actions.py
    subversion/trunk/subversion/tests/cmdline/svntest/main.py
    subversion/trunk/subversion/tests/cmdline/svntest/wc.py

Propchange: subversion/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 16 17:46:37 2015
@@ -58,7 +58,7 @@
 /subversion/branches/log-addressing:1509279-1546844
 /subversion/branches/log-g-performance:870941-871032
 /subversion/branches/merge-skips-obstructions:874525-874615
-/subversion/branches/move-tracking-2:1607334
+/subversion/branches/move-tracking-2:1606692-1714632
 /subversion/branches/multi-layer-moves:1239019-1300930
 /subversion/branches/nfc-nfd-aware-client:870276,870376
 /subversion/branches/node_pool:1304828-1305388

Modified: subversion/trunk/LICENSE
URL: http://svn.apache.org/viewvc/subversion/trunk/LICENSE?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/LICENSE (original)
+++ subversion/trunk/LICENSE Mon Nov 16 17:46:37 2015
@@ -366,3 +366,32 @@ subversion/libsvn_subr/x509.h
  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+For the (modified) 'linenoise' library in tools/dev/svnmover/linenoise
+
+  Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
+  Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+
+  All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Mon Nov 16 17:46:37 2015
@@ -45,6 +45,8 @@ private-includes =
         subversion/bindings/cxxhl/src/private/*.hpp
         subversion/bindings/javahl/native/*.hpp
         subversion/bindings/javahl/native/jniwrapper/jni_*.hpp
+        tools/dev/svnmover/linenoise/linenoise.h
+        tools/dev/svnmover/linenoise/linenoise.c
         subversion/libsvn_subr/utf8proc/utf8proc.h
         subversion/libsvn_subr/utf8proc/utf8proc.c
         subversion/libsvn_subr/utf8proc/utf8proc_data.c
@@ -252,7 +254,7 @@ type = lib
 install = fsmod-lib
 path = subversion/libsvn_delta
 libs = libsvn_subr aprutil apriconv apr zlib
-msvc-export = svn_delta.h private/svn_editor.h private/svn_delta_private.h
+msvc-export = svn_delta.h private/svn_editor.h private/svn_delta_private.h private/svn_element.h private/svn_branch.h private/svn_branch_compat.h private/svn_branch_impl.h private/svn_branch_nested.h private/svn_branch_repos.h
 
 # Routines for diffing
 [libsvn_diff]
@@ -1544,7 +1546,7 @@ path = build/win32
 libs = __ALL_TESTS__
        diff diff3 diff4 fsfs-access-map svnauth 
        svn-populate-node-origins-index x509-parser svn-wc-db-tester
-       svn-mergeinfo-normalizer
+       svn-mergeinfo-normalizer svnmover
 
 [__LIBS__]
 type = project
@@ -1673,3 +1675,12 @@ path = tools/dev
 sources = x509-parser.c
 install = tools
 libs = libsvn_subr apr
+
+[svnmover]
+description = Subversion Mover Command Client
+type = exe
+path = tools/dev/svnmover
+sources = *.c
+libs = libsvn_client libsvn_ra libsvn_subr libsvn_delta apriconv apr
+install = tools
+manpages = tools/dev/svnmover/svnmover.1

Modified: subversion/trunk/configure.ac
URL: http://svn.apache.org/viewvc/subversion/trunk/configure.ac?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/configure.ac (original)
+++ subversion/trunk/configure.ac Mon Nov 16 17:46:37 2015
@@ -1054,7 +1054,7 @@ AS_HELP_STRING([--enable-maintainer-mode
         CFLAGS="$CFLAGS_KEEP"
 
         dnl Add flags that all versions of GCC (should) support
-        CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS"
+        CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS"
       fi
       if test "$GXX" = "yes"; then
         AC_MSG_NOTICE([maintainer-mode: adding G++ warning flags])

Propchange: subversion/trunk/notes/move-tracking/README
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 16 17:46:37 2015
@@ -55,6 +55,7 @@
 /subversion/branches/log-addressing/BRANCH-README:1509279-1546844
 /subversion/branches/log-g-performance/BRANCH-README:870941-871032
 /subversion/branches/merge-skips-obstructions/BRANCH-README:874525-874615
+/subversion/branches/move-tracking-2/notes/move-tracking/README:1714595-1714632
 /subversion/branches/multi-layer-moves/BRANCH-README:1239019-1300930
 /subversion/branches/nfc-nfd-aware-client/BRANCH-README:870276,870376
 /subversion/branches/node_pool/BRANCH-README:1304828-1305388

Modified: subversion/trunk/subversion/include/private/svn_cmdline_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_cmdline_private.h?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_cmdline_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_cmdline_private.h Mon Nov 16 17:46:37 2015
@@ -213,6 +213,18 @@ svn_cmdline__getopt_init(apr_getopt_t **
                          const char *argv[],
                          apr_pool_t *pool);
 
+/*  */
+svn_boolean_t
+svn_cmdline__stdin_is_a_terminal(void);
+
+/*  */
+svn_boolean_t
+svn_cmdline__stdout_is_a_terminal(void);
+
+/*  */
+svn_boolean_t
+svn_cmdline__stderr_is_a_terminal(void);
+
 /* Determine whether interactive mode should be enabled, based on whether
  * the user passed the --non-interactive or --force-interactive options.
  * If neither option was passed, interactivity is enabled if standard

Propchange: subversion/trunk/subversion/libsvn_fs_x/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Mon Nov 16 17:46:37 2015
@@ -58,6 +58,7 @@
 /subversion/branches/log-addressing/subversion/libsvn_fs_x:1511324
 /subversion/branches/log-g-performance/subversion/libsvn_fs_x:870941-871032
 /subversion/branches/merge-skips-obstructions/subversion/libsvn_fs_x:874525-874615
+/subversion/branches/move-tracking-2/subversion/libsvn_fs_x:1606692-1714632
 /subversion/branches/multi-layer-moves/subversion/libsvn_fs_x:1239019-1300930
 /subversion/branches/nfc-nfd-aware-client/subversion/libsvn_fs_x:870276,870376
 /subversion/branches/node_pool/subversion/libsvn_fs_x:1304828-1305388

Modified: subversion/trunk/subversion/libsvn_subr/cmdline.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cmdline.c?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cmdline.c Mon Nov 16 17:46:37 2015
@@ -1171,6 +1171,36 @@ svn_cmdline__print_xml_prop_hash(svn_str
 }
 
 svn_boolean_t
+svn_cmdline__stdin_is_a_terminal(void)
+{
+#ifdef WIN32
+  return (_isatty(STDIN_FILENO) != 0);
+#else
+  return (isatty(STDIN_FILENO) != 0);
+#endif
+}
+
+svn_boolean_t
+svn_cmdline__stdout_is_a_terminal(void)
+{
+#ifdef WIN32
+  return (_isatty(STDOUT_FILENO) != 0);
+#else
+  return (isatty(STDOUT_FILENO) != 0);
+#endif
+}
+
+svn_boolean_t
+svn_cmdline__stderr_is_a_terminal(void)
+{
+#ifdef WIN32
+  return (_isatty(STDERR_FILENO) != 0);
+#else
+  return (isatty(STDERR_FILENO) != 0);
+#endif
+}
+
+svn_boolean_t
 svn_cmdline__be_interactive(svn_boolean_t non_interactive,
                             svn_boolean_t force_interactive)
 {

Modified: subversion/trunk/subversion/tests/cmdline/svntest/actions.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/actions.py?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/actions.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/actions.py Mon Nov 16 17:46:37 2015
@@ -402,6 +402,27 @@ def run_and_verify_svnrdump(dumpfile_con
   return output
 
 
+def run_and_verify_svnmover(expected_stdout, expected_stderr,
+                            *varargs):
+  """Run svnmover command and check its output"""
+
+  expected_exit = 0
+  if expected_stderr is not None and expected_stderr != []:
+    expected_exit = 1
+  return run_and_verify_svnmover2(expected_stdout, expected_stderr,
+                                  expected_exit, *varargs)
+
+def run_and_verify_svnmover2(expected_stdout, expected_stderr,
+                             expected_exit, *varargs):
+  """Run svnmover command and check its output and exit code."""
+
+  exit_code, out, err = main.run_svnmover(*varargs)
+  verify.verify_outputs("Unexpected output", out, err,
+                        expected_stdout, expected_stderr)
+  verify.verify_exit_code("Unexpected return code", exit_code, expected_exit)
+  return exit_code, out, err
+
+
 def run_and_verify_svnmucc(expected_stdout, expected_stderr,
                            *varargs):
   """Run svnmucc command and check its output"""

Modified: subversion/trunk/subversion/tests/cmdline/svntest/main.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/main.py?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/main.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/main.py Mon Nov 16 17:46:37 2015
@@ -179,6 +179,7 @@ svnauthz_binary = os.path.abspath('../..
 svnauthz_validate_binary = os.path.abspath(
     '../../../tools/server-side/svnauthz-validate' + _exe
 )
+svnmover_binary = os.path.abspath('../../../tools/dev/svnmover/svnmover' + _exe)
 
 # Location to the pristine repository, will be calculated from test_area_url
 # when we know what the user specified for --url.
@@ -773,6 +774,12 @@ def run_svnversion(*varargs):
   as list of lines (including line terminators)."""
   return run_command(svnversion_binary, 1, False, *varargs)
 
+def run_svnmover(*varargs):
+  """Run svnmover with VARARGS, returns exit code as int; stdout, stderr as
+  list of lines (including line terminators)."""
+  return run_command(svnmover_binary, 1, False,
+                     *(_with_auth(_with_config_dir(varargs))))
+
 def run_svnmucc(*varargs):
   """Run svnmucc with VARARGS, returns exit code as int; stdout, stderr as
   list of lines (including line terminators).  Use binary mode for output."""
@@ -2188,6 +2195,7 @@ def execute_tests(test_list, serial_only
   global svnsync_binary
   global svndumpfilter_binary
   global svnversion_binary
+  global svnmover_binary
   global svnmucc_binary
   global svnauthz_binary
   global svnauthz_validate_binary
@@ -2286,6 +2294,7 @@ def execute_tests(test_list, serial_only
     svnauthz_binary = os.path.join(options.tools_bin, 'svnauthz' + _exe)
     svnauthz_validate_binary = os.path.join(options.tools_bin,
                                             'svnauthz-validate' + _exe)
+    svnmover_binary = os.path.join(options.tools_bin, 'svnmover' + _exe)
 
   ######################################################################
 

Modified: subversion/trunk/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/wc.py?rev=1714640&r1=1714639&r2=1714640&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/wc.py Mon Nov 16 17:46:37 2015
@@ -116,6 +116,14 @@ _re_parse_co_restored = re.compile('^(Re
 _re_parse_commit_ext = re.compile('^(([A-Za-z]+( [a-z]+)*)) \'(.+)\'( --.*)?')
 _re_parse_commit = re.compile('^(\w+(  \(bin\))?)\s+(.+)')
 
+#rN: eids 0 15 branches 4
+_re_parse_eid_header = re.compile('^r(-1|[0-9]+): eids ([0-9]+) ([0-9]+) '
+                                  'branches ([0-9]+)$')
+# B0.2 root-eid 3
+_re_parse_eid_branch = re.compile('^(B[0-9.]+) root-eid ([0-9]+) num-eids ([0-9]+)( from [^ ]*)?$')
+# e4: normal 6 C
+_re_parse_eid_ele = re.compile('^e([0-9]+): (none|normal|subbranch) '
+                               '(-1|[0-9]+) (.*)$')
 
 class State:
   """Describes an existing or expected state of a working copy.
@@ -206,6 +214,30 @@ class State:
       if list(filter(path, item)):
         item.tweak(**kw)
 
+  def rename(self, moves):
+    """Change the path of some items.
+
+    MOVES is a dictionary mapping source path to destination
+    path. Children move with moved parents.  All subtrees are moved in
+    reverse depth order to temporary storage before being moved in
+    depth order to the final location.  This allows nested moves.
+
+    """
+    temp = {}
+    for src, dst in sorted(moves.items(), key=lambda (src, dst): src)[::-1]:
+      temp[src] = {}
+      for path, item in self.desc.items():
+        if path == src or path[:len(src) + 1] == src + '/':
+          temp[src][path] = item;
+          del self.desc[path]
+    for src, dst in sorted(moves.items(), key=lambda (src, dst): dst):
+      for path, item in temp[src].items():
+        if path == src:
+          new_path = dst
+        else:
+          new_path = dst + path[len(src):]
+        self.desc[new_path] = item
+
   def subtree(self, subtree_path):
     """Return a State object which is a deep copy of the sub-tree
     beneath SUBTREE_PATH (which is assumed to be rooted at the tree of
@@ -750,6 +782,58 @@ class State:
 
     return cls('', desc)
 
+  @classmethod
+  def from_eids(cls, lines):
+
+    # Need to read all elements in a branch before we can construct
+    # the full path to an element.
+    # For the full path we use <branch-id>/<path-within-branch>.
+
+    def eid_path(eids, eid):
+      ele = eids[eid]
+      if ele[0] == '-1':
+        return ele[1]
+      parent_path = eid_path(eids, ele[0])
+      if parent_path == '':
+        return ele[1]
+      return parent_path + '/' + ele[1]
+
+    def eid_full_path(eids, eid, branch_id):
+      path = eid_path(eids, eid)
+      if path == '':
+        return branch_id
+      return branch_id + '/' + path
+
+    def add_to_desc(eids, desc, branch_id):
+      for k, v in eids.items():
+        desc[eid_full_path(eids, k, branch_id)] = StateItem(eid=k)
+
+    branch_id = None
+    eids = {}
+    desc = {}
+    for line in lines:
+
+      match = _re_parse_eid_ele.search(line)
+      if match and match.group(2) != 'none':
+        eid = match.group(1)
+        parent_eid = match.group(3) 
+        path = match.group(4)
+        if path == '.':
+          path = ''
+        eids[eid] = [parent_eid, path]
+
+      match = _re_parse_eid_branch.search(line)
+      if match:
+        if branch_id:
+          add_to_desc(eids, desc, branch_id)
+          eids = {}
+        branch_id = match.group(1)
+        root_eid = match.group(2)
+
+    add_to_desc(eids, desc, branch_id)
+
+    return cls('', desc)
+  
 
 class StateItem:
   """Describes an individual item within a working copy.
@@ -764,7 +848,8 @@ class StateItem:
                entry_rev=None, entry_status=None, entry_copied=None,
                locked=None, copied=None, switched=None, writelocked=None,
                treeconflict=None, moved_from=None, moved_to=None,
-               prev_status=None, prev_verb=None, prev_treeconflict=None):
+               prev_status=None, prev_verb=None, prev_treeconflict=None,
+               eid=None):
     # provide an empty prop dict if it wasn't provided
     if props is None:
       props = { }
@@ -772,6 +857,8 @@ class StateItem:
     ### keep/make these ints one day?
     if wc_rev is not None:
       wc_rev = str(wc_rev)
+    if eid is not None:
+      eid = str(eid)
 
     # Any attribute can be None if not relevant, unless otherwise stated.
 
@@ -807,6 +894,7 @@ class StateItem:
     # Relative paths to the move locations
     self.moved_from = moved_from
     self.moved_to = moved_to
+    self.eid = eid
 
   def copy(self):
     "Make a deep copy of self."
@@ -820,6 +908,8 @@ class StateItem:
       # Refine the revision args (for now) to ensure they are strings.
       if value is not None and name == 'wc_rev':
         value = str(value)
+      if value is not None and name == 'eid':
+        value = str(value)
       setattr(self, name, value)
 
   def __eq__(self, other):
@@ -867,6 +957,8 @@ class StateItem:
       atts['moved_from'] = self.moved_from
     if self.moved_to is not None:
       atts['moved_to'] = self.moved_to
+    if self.eid is not None:
+      atts['eid'] = self.eid
 
     return (os.path.normpath(path), self.contents, self.props, atts)