You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by da...@apache.org on 2010/04/23 20:58:02 UTC

svn commit: r937468 - in /subversion/trunk/subversion: include/private/svn_wc_private.h include/svn_wc.h libsvn_wc/node.c libsvn_wc/status.c svn/status-cmd.c svn/status.c tests/cmdline/copy_tests.py tests/cmdline/merge_tests.py tests/cmdline/svntest/wc.py

Author: dannas
Date: Fri Apr 23 18:58:01 2010
New Revision: 937468

URL: http://svn.apache.org/viewvc?rev=937468&view=rev
Log:
As part of WC-NG, replace entry calls for revisions from
svn_wc_status3_t related code. While doing that, we define a strict
idea of what a revision in svn_wc_status3_t means. The revision returned
from libsvn_wc is:

  "The revision of the unmodified (BASE) node, or SVN_INVALID_REVNUM if
  any (structural) changes have been made to that node."

We have three compability concerns to address:
1) svn_wc_status3_t only gives us the revision information for BASE.
   svn_wc__node_get_working_rev_info() is used for returning the WORKING
   state as the entries code would have done it.

2) The entries code set the revision of newly added nodes to 0 but the
   db sets them to -1. Since too many tests needs to be changed and 'svn
   info' also uses 0, I'll change those values in a follow-up patch
   instead.

3) Despite the attempt to mimic the semantics of the entries code, we
   have two changes in behaviour. An entry_rev field has been added to
   StateItem to allow the testsuite to handle those differences.

* subversion/tests/cmdline/copy_tests.py
  (repos_to_wc): Change revision to 0 since the node is added. Don't
    check against entries since the behavior differs.

* subversion/tests/cmdline/svntest/wc.py
  (tweak_for_entries_compare): Set wc_rev to entry_rev when the later
    exists. Clear entry_rev afterwards to avoid it interfering when
    doing the compare between the output from entries-dump and our
    state.
  (StateItem): Add new member entry_rev for tracking differences in
    behaviour between WC-1 code and WC-NG.

* subversion/tests/cmdline/merge_tests.py
  (merge_into_missing): Add revision to status output for missing dir.
    Previously, missing dirs did not have a revision, only files had.
    Don't check entries since the behavior differs.

* subversion/svn/status.c
  (print_status): Replace checks for revisions using entries with the
    direct fields in svn_wc_status3_t. Set the revision for added and
    replaced nodes to 0. WC-NG sets those revisions to -1, but changing
    all the involved tests is for a follow-up.

* subversion/include/svn_wc.h
  (svn_wc_status2_t): Add fields revision, changed_rev, changed_date and
    changed_author.

* subversion/include/private/svn_wc_private.h
  (svn_wc__node_get_working_rev_info): Declare. New.

* subversion/libsvn_wc/node.c
  (svn_wc__node__get_working_rev_info): New.

* subversion/libsvn_wc/status.c
  (assemble_status): Fill in the new fields with data from the wc db.
  (svn_wc_dup_status3): Copy the changed_author field.

* subversion/svn/status-cmd.c
  (status_baton): Add svn_client_ctx member. 
  (print_status): Fetch revision information about WORKING nodes with
    svn_wc__node_get_working_rev(). It's a temporary thing until we've
    decided what behaviour we prefer and the means for detecting what
    state the wc is in.
  (svn_cl__status): Set ctx member of status_baton.

Modified:
    subversion/trunk/subversion/include/private/svn_wc_private.h
    subversion/trunk/subversion/include/svn_wc.h
    subversion/trunk/subversion/libsvn_wc/node.c
    subversion/trunk/subversion/libsvn_wc/status.c
    subversion/trunk/subversion/svn/status-cmd.c
    subversion/trunk/subversion/svn/status.c
    subversion/trunk/subversion/tests/cmdline/copy_tests.py
    subversion/trunk/subversion/tests/cmdline/merge_tests.py
    subversion/trunk/subversion/tests/cmdline/svntest/wc.py

Modified: subversion/trunk/subversion/include/private/svn_wc_private.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/private/svn_wc_private.h?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/include/private/svn_wc_private.h (original)
+++ subversion/trunk/subversion/include/private/svn_wc_private.h Fri Apr 23 18:58:01 2010
@@ -487,6 +487,41 @@ svn_wc__node_get_base_rev(svn_revnum_t *
                           const char *local_abspath,
                           apr_pool_t *scratch_pool);
 
+
+/* Get the working revision of @a local_abspath using @a wc_ctx. If @a
+ * local_abspath is not in the working copy, return @c
+ * SVN_ERR_WC_PATH_NOT_FOUND.  
+ *
+ * This function is meant as a temporary solution for using the old-style
+ * semantics of entries. It will handle any uncommitted changes (delete,
+ * replace and/or copy-here/move-here).
+ *
+ * For a delete the @a revision is the BASE node of the operation root, e.g
+ * the path that was deleted. But if the delete is  below an add, the
+ * revision is set to SVN_INVALID_REVNUM. For an add, copy or move we return
+ * SVN_INVALID_REVNUM. In case of a replacement, we return the BASE
+ * revision. 
+ *
+ * The @changed_rev is set to the latest committed change to @a
+ * local_abspath before or equal to @a revision, unless the node is
+ * copied-here or moved-here. Then it is the revision of the latest committed
+ * change before or equal to the copyfrom_rev.  NOTE, that we use
+ * SVN_INVALID_REVNUM for a scheduled copy or move. 
+ *
+ * The @a changed_date and @a changed_author are the ones associated with @a
+ * changed_rev.  
+ */
+svn_error_t *
+svn_wc__node_get_working_rev_info(svn_revnum_t *revision,
+                                  svn_revnum_t *changed_rev, 
+                                  apr_time_t *changed_date, 
+                                  const char **changed_author,
+                                  svn_wc_context_t *wc_ctx, 
+                                  const char *local_abspath, 
+                                  apr_pool_t *scratch_pool,
+                                  apr_pool_t *result_pool);
+
+
 /** This whole function is for legacy, and it sucks. It does not really
  * make sense to get the copy-from revision number without the copy-from
  * URL, but higher level code currently wants that. This should go away.

Modified: subversion/trunk/subversion/include/svn_wc.h
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/include/svn_wc.h?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/include/svn_wc.h (original)
+++ subversion/trunk/subversion/include/svn_wc.h Fri Apr 23 18:58:01 2010
@@ -3617,6 +3617,18 @@ typedef struct svn_wc_status3_t
    */
   enum svn_wc_status_kind pristine_prop_status;
 
+  /** Base revision.  */
+  svn_revnum_t revision;
+
+  /** Last revision this was changed */
+  svn_revnum_t changed_rev;
+
+  /** Last commit author of this item */
+  const char *changed_author;
+
+  /** Date of last commit. */
+  apr_time_t changed_date;
+
   /* NOTE! Please update svn_wc_dup_status3() when adding new fields here. */
 } svn_wc_status3_t;
 

Modified: subversion/trunk/subversion/libsvn_wc/node.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/node.c?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/node.c (original)
+++ subversion/trunk/subversion/libsvn_wc/node.c Fri Apr 23 18:58:01 2010
@@ -754,6 +754,68 @@ svn_wc__node_get_base_rev(svn_revnum_t *
 }
 
 svn_error_t *
+svn_wc__node_get_working_rev_info(svn_revnum_t *revision,
+                                  svn_revnum_t *changed_rev, 
+                                  apr_time_t *changed_date, 
+                                  const char **changed_author,
+                                  svn_wc_context_t *wc_ctx, 
+                                  const char *local_abspath, 
+                                  apr_pool_t *scratch_pool,
+                                  apr_pool_t *result_pool)
+{
+  svn_wc__db_status_t status;
+  svn_boolean_t base_shadowed;
+
+  SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, NULL, NULL, NULL,
+                               changed_rev, changed_date, changed_author,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, &base_shadowed, NULL,
+                               NULL, wc_ctx->db, local_abspath, result_pool,
+                               scratch_pool));
+
+  if (status == svn_wc__db_status_deleted)
+    {
+      const char *work_del_abspath = NULL;
+      const char *base_del_abspath = NULL;
+
+      SVN_ERR(svn_wc__db_scan_deletion(&base_del_abspath, NULL,
+                                       NULL, &work_del_abspath, wc_ctx->db,
+                                       local_abspath, scratch_pool,
+                                       result_pool));
+      if (work_del_abspath)
+        {
+          SVN_ERR(svn_wc__db_read_info(&status, NULL, revision, NULL, NULL,
+                                       NULL, changed_rev, changed_date,
+                                       changed_author, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, &base_shadowed,
+                                       NULL, NULL, wc_ctx->db, work_del_abspath,
+                                       result_pool, scratch_pool));
+        }
+      else
+        {
+          SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, revision, NULL,
+                                           NULL, NULL, changed_rev,
+                                           changed_date, changed_author,
+                                           NULL, NULL, NULL, NULL, NULL,
+                                           NULL, wc_ctx->db,
+                                           base_del_abspath, result_pool,
+                                           scratch_pool));
+        }
+    }
+  else if (base_shadowed)
+    {
+      SVN_ERR(svn_wc__db_base_get_info(NULL, NULL, revision, NULL, NULL,
+                                       NULL, changed_rev, changed_date,
+                                       changed_author, NULL, NULL, NULL,
+                                       NULL, NULL, NULL, wc_ctx->db, local_abspath,
+                                       result_pool, scratch_pool));
+    }
+  return SVN_NO_ERROR;
+}
+
+
+svn_error_t *
 svn_wc__node_get_commit_base_rev(svn_revnum_t *commit_base_revision,
                                  svn_wc_context_t *wc_ctx,
                                  const char *local_abspath,

Modified: subversion/trunk/subversion/libsvn_wc/status.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_wc/status.c?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_wc/status.c (original)
+++ subversion/trunk/subversion/libsvn_wc/status.c Fri Apr 23 18:58:01 2010
@@ -297,6 +297,11 @@ assemble_status(svn_wc_status3_t **statu
   svn_boolean_t switched_p = FALSE;
   const svn_wc_conflict_description2_t *tree_conflict;
   svn_boolean_t file_external_p = FALSE;
+  svn_revnum_t revision;
+  svn_revnum_t changed_rev;
+  const char *changed_author;
+  apr_time_t changed_date;
+  svn_boolean_t base_shadowed;
 #ifdef HAVE_SYMLINK
   svn_boolean_t wc_special;
 #endif /* HAVE_SYMLINK */
@@ -376,6 +381,10 @@ assemble_status(svn_wc_status3_t **statu
 
       stat->repos_lock = repos_lock;
       stat->url = NULL;
+      stat->revision = SVN_INVALID_REVNUM;
+      stat->changed_rev = SVN_INVALID_REVNUM;
+      stat->changed_author = NULL;
+      stat->changed_date = 0;
       stat->ood_last_cmt_rev = SVN_INVALID_REVNUM;
       stat->ood_last_cmt_date = 0;
       stat->ood_kind = svn_node_none;
@@ -385,6 +394,13 @@ assemble_status(svn_wc_status3_t **statu
       return SVN_NO_ERROR;
     }
 
+  SVN_ERR(svn_wc__db_read_info(NULL, NULL, &revision, NULL, NULL, NULL,
+                               &changed_rev, &changed_date, &changed_author,
+                               NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL, &base_shadowed, NULL,
+                               NULL, db, local_abspath, result_pool,
+                               scratch_pool));
+
   /* Someone either deleted the administrative directory in the versioned
      subdir, or deleted the directory altogether and created a new one.
      In any case, what is currently there is in the way.
@@ -606,6 +622,10 @@ assemble_status(svn_wc_status3_t **statu
   stat->copied = entry->copied;
   stat->repos_lock = repos_lock;
   stat->url = (entry->url ? entry->url : NULL);
+  stat->revision = revision;
+  stat->changed_rev = changed_rev;
+  stat->changed_author = changed_author;
+  stat->changed_date = changed_date;
   stat->ood_last_cmt_rev = SVN_INVALID_REVNUM;
   stat->ood_last_cmt_date = 0;
   stat->ood_kind = svn_node_none;
@@ -2459,6 +2479,9 @@ svn_wc_dup_status3(const svn_wc_status3_
   if (orig_stat->url)
     new_stat->url = apr_pstrdup(pool, orig_stat->url);
 
+  if (orig_stat->changed_author)
+    new_stat->changed_author = apr_pstrdup(pool, orig_stat->changed_author);
+
   if (orig_stat->ood_last_cmt_author)
     new_stat->ood_last_cmt_author
       = apr_pstrdup(pool, orig_stat->ood_last_cmt_author);

Modified: subversion/trunk/subversion/svn/status-cmd.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/status-cmd.c?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/status-cmd.c (original)
+++ subversion/trunk/subversion/svn/status-cmd.c Fri Apr 23 18:58:01 2010
@@ -40,6 +40,7 @@
 #include "cl.h"
 
 #include "svn_private_config.h"
+#include "private/svn_wc_private.h"
 
 
 
@@ -65,6 +66,8 @@ struct status_baton
   unsigned int text_conflicts;
   unsigned int prop_conflicts;
   unsigned int tree_conflicts;
+
+  svn_client_ctx_t *ctx;
 };
 
 
@@ -167,6 +170,35 @@ print_status(void *baton,
              apr_pool_t *pool)
 {
   struct status_baton *sb = baton;
+  svn_wc_status3_t *tweaked_status;
+  svn_revnum_t revision;
+  svn_revnum_t changed_rev;
+  apr_time_t changed_date;
+  const char *changed_author;
+  const char *local_abspath;
+
+  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, sb->cl_pool));
+  tweaked_status = svn_wc_dup_status3(status, sb->cl_pool);
+
+  /* ### The revision information with associates are based on what
+   * ### _read_info() returns. The svn_wc_status_func4_t callback is
+   * ### suppposed to handle the gathering of additional information from the
+   * ### WORKING nodes on its own. Until we've agreed on how the CLI should
+   * ### handle the revision information, we use this appproach to stay compat
+   * ### with our testsuite. */
+  if (status->entry)
+    {
+      SVN_ERR(svn_wc__node_get_working_rev_info(&revision, &changed_rev,
+                                                &changed_date,
+                                                &changed_author,
+                                                sb->ctx->wc_ctx,
+                                                local_abspath, sb->cl_pool,
+                                                pool));
+      tweaked_status->revision = revision;
+      tweaked_status->changed_rev = changed_rev;
+      tweaked_status->changed_date = changed_date;
+      tweaked_status->changed_author = changed_author;
+    }
 
   /* If there's a changelist attached to the entry, then we don't print
      the item, but instead dup & cache the status structure for later. */
@@ -178,7 +210,7 @@ print_status(void *baton,
       const char *cl_key = apr_pstrdup(sb->cl_pool, status->entry->changelist);
       struct status_cache *scache = apr_pcalloc(sb->cl_pool, sizeof(*scache));
       scache->path = apr_pstrdup(sb->cl_pool, path);
-      scache->status = svn_wc_dup_status3(status, sb->cl_pool);
+      scache->status = svn_wc_dup_status3(tweaked_status, sb->cl_pool);
 
       path_array =
         apr_hash_get(sb->cached_changelists, cl_key, APR_HASH_KEY_STRING);
@@ -194,7 +226,7 @@ print_status(void *baton,
       return SVN_NO_ERROR;
     }
 
-  return print_status_normal_or_xml(baton, path, status, pool);
+  return print_status_normal_or_xml(baton, path, tweaked_status, pool);
 }
 
 /* This implements the `svn_opt_subcommand_t' interface. */
@@ -255,6 +287,7 @@ svn_cl__status(apr_getopt_t *os,
   sb.text_conflicts = 0;
   sb.prop_conflicts = 0;
   sb.tree_conflicts = 0;
+  sb.ctx = ctx;
 
   SVN_ERR(svn_opt_eat_peg_revisions(&targets, targets, scratch_pool));
 

Modified: subversion/trunk/subversion/svn/status.c
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/svn/status.c?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/svn/status.c (original)
+++ subversion/trunk/subversion/svn/status.c Fri Apr 23 18:58:01 2010
@@ -142,12 +142,20 @@ print_status(const char *path,
 
       if (! status->entry)
         working_rev = "";
-      else if (! SVN_IS_VALID_REVNUM(status->entry->revision))
-        working_rev = " ? ";
+      else if (! SVN_IS_VALID_REVNUM(status->revision))
+        {
+          if (status->copied)
+            working_rev = "-";
+          else if (text_status == svn_wc_status_added
+              || text_status == svn_wc_status_replaced)
+            working_rev = "0";
+          else
+            working_rev = " ? ";
+        }
       else if (status->copied)
         working_rev = "-";
       else
-        working_rev = apr_psprintf(pool, "%ld", status->entry->revision);
+        working_rev = apr_psprintf(pool, "%ld", status->revision);
 
       if (status->repos_text_status != svn_wc_status_none
           || status->repos_prop_status != svn_wc_status_none)
@@ -183,15 +191,15 @@ print_status(const char *path,
           const char *commit_rev;
           const char *commit_author;
 
-          if (status->entry && SVN_IS_VALID_REVNUM(status->entry->cmt_rev))
-            commit_rev = apr_psprintf(pool, "%ld", status->entry->cmt_rev);
+          if (SVN_IS_VALID_REVNUM(status->changed_rev))
+            commit_rev = apr_psprintf(pool, "%ld", status->changed_rev);
           else if (status->entry)
             commit_rev = " ? ";
           else
             commit_rev = "";
 
-          if (status->entry && status->entry->cmt_author)
-            commit_author = status->entry->cmt_author;
+          if (status->changed_author)
+            commit_author = status->changed_author;
           else if (status->entry)
             commit_author = " ? ";
           else
@@ -277,17 +285,17 @@ svn_cl__print_status_xml(const char *pat
     apr_hash_set(att_hash, "file-external", APR_HASH_KEY_STRING, "true");
   if (status->entry && ! status->entry->copied)
     apr_hash_set(att_hash, "revision", APR_HASH_KEY_STRING,
-                 apr_psprintf(pool, "%ld", status->entry->revision));
+                 apr_psprintf(pool, "%ld", status->revision));
   if (status->tree_conflict)
     apr_hash_set(att_hash, "tree-conflicted", APR_HASH_KEY_STRING,
                  "true");
   svn_xml_make_open_tag_hash(&sb, pool, svn_xml_normal, "wc-status",
                              att_hash);
 
-  if (status->entry && SVN_IS_VALID_REVNUM(status->entry->cmt_rev))
+  if (SVN_IS_VALID_REVNUM(status->changed_rev))
     {
-      svn_cl__print_xml_commit(&sb, status->entry->cmt_rev,
-                               status->entry->cmt_author,
+      svn_cl__print_xml_commit(&sb, status->changed_rev,
+                               status->changed_author,
                                svn_time_to_cstring(status->entry->cmt_date,
                                                    pool),
                                pool);

Modified: subversion/trunk/subversion/tests/cmdline/copy_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/copy_tests.py?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/copy_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/copy_tests.py Fri Apr 23 18:58:01 2010
@@ -980,7 +980,7 @@ def repos_to_wc(sbox):
 
   expected_output = svntest.actions.get_virginal_state(wc_dir, 1)
   expected_output.add({
-    'pi' : Item(status='A ',  wc_rev='1'),
+    'pi' : Item(status='A ',  wc_rev='0', entry_rev='1'),
     })
   svntest.actions.run_and_verify_status(wc_dir, expected_output)
 

Modified: subversion/trunk/subversion/tests/cmdline/merge_tests.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/merge_tests.py?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/merge_tests.py (original)
+++ subversion/trunk/subversion/tests/cmdline/merge_tests.py Fri Apr 23 18:58:01 2010
@@ -2161,7 +2161,7 @@ def merge_into_missing(sbox):
   expected_status = wc.State(F_path, {
     ''      : Item(status='  ', wc_rev=1),
     'foo'   : Item(status='! ', wc_rev=2),
-    'Q'     : Item(status='! ', wc_rev='?'),
+    'Q'     : Item(status='! ', wc_rev='2', entry_rev='?'),
     })
   expected_skip = wc.State(F_path, {
     'Q'   : Item(),
@@ -2183,7 +2183,7 @@ def merge_into_missing(sbox):
   expected_status = wc.State(F_path, {
     ''      : Item(status=' M', wc_rev=1),
     'foo'   : Item(status='!M', wc_rev=2),
-    'Q'     : Item(status='! ', wc_rev='?'),
+    'Q'     : Item(status='! ', wc_rev='2', entry_rev='?'),
     })
   expected_mergeinfo_output = wc.State(F_path, {
     ''    : Item(status=' U'),
@@ -2214,7 +2214,7 @@ def merge_into_missing(sbox):
   expected_status.add({
     'A/B/F'     : Item(status=' M', wc_rev=1),
     'A/B/F/foo' : Item(status='!M', wc_rev=2),
-    'A/B/F/Q'   : Item(status='! ', wc_rev='?'),
+    'A/B/F/Q'   : Item(status='! ', wc_rev='2', entry_rev='?'),
     })
   svntest.actions.run_and_verify_status(wc_dir, expected_status)
 

Modified: subversion/trunk/subversion/tests/cmdline/svntest/wc.py
URL: http://svn.apache.org/viewvc/subversion/trunk/subversion/tests/cmdline/svntest/wc.py?rev=937468&r1=937467&r2=937468&view=diff
==============================================================================
--- subversion/trunk/subversion/tests/cmdline/svntest/wc.py (original)
+++ subversion/trunk/subversion/tests/cmdline/svntest/wc.py Fri Apr 23 18:58:01 2010
@@ -317,6 +317,9 @@ class State:
             item.status = ' ' + item.status[1]
           if item.status[1] == 'M':
             item.status = item.status[0] + ' '
+          if item.entry_rev is not None:
+            item.wc_rev = item.entry_rev
+            item.entry_rev = None
       if item.writelocked:
         # we don't contact the repository, so our only information is what
         # is in the working copy. 'K' means we have one and it matches the
@@ -615,7 +618,7 @@ class StateItem:
   """
 
   def __init__(self, contents=None, props=None,
-               status=None, verb=None, wc_rev=None,
+               status=None, verb=None, wc_rev=None, entry_rev=None,
                locked=None, copied=None, switched=None, writelocked=None,
                treeconflict=None):
     # provide an empty prop dict if it wasn't provided
@@ -638,6 +641,9 @@ class StateItem:
     self.verb = verb
     # The base revision number of the node in the WC, as a string.
     self.wc_rev = wc_rev
+    # This one will be set when we expect the wc_rev to differ from the one
+    # found ni the entries code.
+    self.entry_rev = entry_rev
     # For the following attributes, the value is the status character of that
     # field from 'svn status', except using value None instead of status ' '.
     self.locked = locked