diff options
Diffstat (limited to 'subversion/libsvn_wc/diff_editor.c')
| -rw-r--r-- | subversion/libsvn_wc/diff_editor.c | 182 | 
1 files changed, 152 insertions, 30 deletions
| diff --git a/subversion/libsvn_wc/diff_editor.c b/subversion/libsvn_wc/diff_editor.c index fc059a5d4dea..9b1b0d50baa0 100644 --- a/subversion/libsvn_wc/diff_editor.c +++ b/subversion/libsvn_wc/diff_editor.c @@ -145,6 +145,9 @@ struct dir_baton_t    /* TRUE if the node is to be compared with an unrelated node*/    svn_boolean_t ignoring_ancestry; +  /* TRUE if the directory was reported incomplete to the repository */ +  svn_boolean_t is_incomplete; +    /* Processor state */    void *pdb;    svn_boolean_t skip; @@ -741,9 +744,29 @@ walk_local_nodes_diff(struct edit_baton_t *eb,            if (eb->local_before_remote && local_only)              { +              const char *moved_from_relpath; + +              if (info->moved_here) +                { +                  const char *moved_from_abspath; + +                  SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, +                                                NULL, NULL, NULL, +                                                db, child_abspath, +                                                iterpool, iterpool)); +                  SVN_ERR_ASSERT(moved_from_abspath != NULL); + +                  moved_from_relpath = svn_dirent_skip_ancestor( +                                                        eb->anchor_abspath, +                                                        moved_from_abspath); +                } +              else +                moved_from_relpath = NULL; +                if (info->kind == svn_node_file && diff_files)                  SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,                                                       child_relpath, +                                                     moved_from_relpath,                                                       eb->processor, dir_baton,                                                       eb->diff_pristine,                                                       eb->cancel_func, @@ -753,6 +776,7 @@ walk_local_nodes_diff(struct edit_baton_t *eb,                  SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,                                                      child_relpath,                                                      depth_below_here, +                                                    moved_from_relpath,                                                      eb->processor, dir_baton,                                                      eb->diff_pristine,                                                      eb->cancel_func, @@ -807,9 +831,29 @@ walk_local_nodes_diff(struct edit_baton_t *eb,            if (!eb->local_before_remote && local_only)              { +              const char *moved_from_relpath; + +              if (info->moved_here) +                { +                  const char *moved_from_abspath; + +                  SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, +                                                NULL, NULL, NULL, +                                                db, child_abspath, +                                                iterpool, iterpool)); +                  SVN_ERR_ASSERT(moved_from_abspath != NULL); + +                  moved_from_relpath = svn_dirent_skip_ancestor( +                                                        eb->anchor_abspath, +                                                        moved_from_abspath); +                } +              else +                moved_from_relpath = NULL; +                if (info->kind == svn_node_file && diff_files)                  SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,                                                       child_relpath, +                                                     moved_from_relpath,                                                       eb->processor, dir_baton,                                                       eb->diff_pristine,                                                       eb->cancel_func, @@ -817,12 +861,13 @@ walk_local_nodes_diff(struct edit_baton_t *eb,                                                       iterpool));                else if (info->kind == svn_node_dir && diff_dirs)                  SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath, -                                                     child_relpath, depth_below_here, -                                                     eb->processor, dir_baton, -                                                     eb->diff_pristine, -                                                     eb->cancel_func, -                                                     eb->cancel_baton, -                                                     iterpool)); +                                                    child_relpath, depth_below_here, +                                                    moved_from_relpath, +                                                    eb->processor, dir_baton, +                                                    eb->diff_pristine, +                                                    eb->cancel_func, +                                                    eb->cancel_baton, +                                                    iterpool));              }          }      } @@ -873,6 +918,7 @@ svn_error_t *  svn_wc__diff_local_only_file(svn_wc__db_t *db,                               const char *local_abspath,                               const char *relpath, +                             const char *moved_from_relpath,                               const svn_diff_tree_processor_t *processor,                               void *processor_parent_baton,                               svn_boolean_t diff_pristine, @@ -935,6 +981,7 @@ svn_wc__diff_local_only_file(svn_wc__db_t *db,      {        copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);        copyfrom_src->repos_relpath = original_repos_relpath; +      copyfrom_src->moved_from_relpath = moved_from_relpath;      }    if (props_mod || !SVN_IS_VALID_REVNUM(revision)) @@ -1013,6 +1060,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,                              const char *local_abspath,                              const char *relpath,                              svn_depth_t depth, +                            const char *moved_from_relpath,                              const svn_diff_tree_processor_t *processor,                              void *processor_parent_baton,                              svn_boolean_t diff_pristine, @@ -1049,6 +1097,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,      {        copyfrom_src = svn_diff__source_create(original_revision, scratch_pool);        copyfrom_src->repos_relpath = original_repos_relpath; +      copyfrom_src->moved_from_relpath = moved_from_relpath;      }    /* svn_wc__db_status_incomplete should never happen, as the result won't be @@ -1136,12 +1185,40 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,            child_relpath = svn_relpath_join(relpath, name, iterpool); +          if (info->moved_here) +            { +              const char *moved_from_abspath; +              const char *a_abspath; +              const char *a_relpath; + +              a_relpath = relpath; +              a_abspath = local_abspath; +              while (*a_relpath) +                { +                  a_relpath = svn_relpath_dirname(a_relpath, iterpool); +                  a_abspath = svn_dirent_dirname(a_abspath, iterpool); +                } + +              SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, +                                            NULL, NULL, NULL, +                                            db, child_abspath, +                                            iterpool, iterpool)); +              SVN_ERR_ASSERT(moved_from_abspath != NULL); + +              moved_from_relpath = svn_dirent_skip_ancestor( +                                                        a_abspath, +                                                        moved_from_abspath); +            } +          else +            moved_from_relpath = NULL; +            switch (info->kind)              {              case svn_node_file:              case svn_node_symlink:                SVN_ERR(svn_wc__diff_local_only_file(db, child_abspath,                                                     child_relpath, +                                                   moved_from_relpath,                                                     processor, pdb,                                                     diff_pristine,                                                     cancel_func, cancel_baton, @@ -1154,6 +1231,7 @@ svn_wc__diff_local_only_dir(svn_wc__db_t *db,                    SVN_ERR(svn_wc__diff_local_only_dir(db, child_abspath,                                                        child_relpath,                                                        depth_below_here, +                                                      moved_from_relpath,                                                        processor, pdb,                                                        diff_pristine,                                                        cancel_func, @@ -1202,6 +1280,8 @@ handle_local_only(struct dir_baton_t *pb,  {    struct edit_baton_t *eb = pb->eb;    const struct svn_wc__db_info_t *info; +  const char *child_abspath; +  const char *moved_from_relpath;    svn_boolean_t repos_delete = (pb->deletes                                  && svn_hash_gets(pb->deletes, name)); @@ -1220,10 +1300,8 @@ handle_local_only(struct dir_baton_t *pb,    switch (info->status)      { -      case svn_wc__db_status_incomplete: -        return SVN_NO_ERROR; /* Not local only */ -        case svn_wc__db_status_normal: +      case svn_wc__db_status_incomplete:          if (!repos_delete)            return SVN_NO_ERROR; /* Local and remote */          svn_hash_sets(pb->deletes, name, NULL); @@ -1239,6 +1317,25 @@ handle_local_only(struct dir_baton_t *pb,          break;      } +  child_abspath = svn_dirent_join(pb->local_abspath, name, scratch_pool); + +  if (info->moved_here) +    { +      const char *moved_from_abspath; + +      SVN_ERR(svn_wc__db_scan_moved(&moved_from_abspath, +                                    NULL, NULL, NULL, +                                    eb->db, child_abspath, +                                    scratch_pool, scratch_pool)); +      SVN_ERR_ASSERT(moved_from_abspath != NULL); + +      moved_from_relpath = svn_dirent_skip_ancestor( +                                    eb->anchor_abspath, +                                    moved_from_abspath); +    } +  else +    moved_from_relpath = NULL; +    if (info->kind == svn_node_dir)      {        svn_depth_t depth ; @@ -1250,9 +1347,10 @@ handle_local_only(struct dir_baton_t *pb,        SVN_ERR(svn_wc__diff_local_only_dir(                        eb->db, -                      svn_dirent_join(pb->local_abspath, name, scratch_pool), +                      child_abspath,                        svn_relpath_join(pb->relpath, name, scratch_pool),                        repos_delete ? svn_depth_infinity : depth, +                      moved_from_relpath,                        eb->processor, pb->pdb,                        eb->diff_pristine,                        eb->cancel_func, eb->cancel_baton, @@ -1261,8 +1359,9 @@ handle_local_only(struct dir_baton_t *pb,    else      SVN_ERR(svn_wc__diff_local_only_file(                        eb->db, -                      svn_dirent_join(pb->local_abspath, name, scratch_pool), +                      child_abspath,                        svn_relpath_join(pb->relpath, name, scratch_pool), +                      moved_from_relpath,                        eb->processor, pb->pdb,                        eb->diff_pristine,                        eb->cancel_func, eb->cancel_baton, @@ -1608,25 +1707,47 @@ open_directory(const char *path,          db->repos_only = TRUE;        if (!db->repos_only) -        switch (info->status) -          { -            case svn_wc__db_status_normal: -              break; -            case svn_wc__db_status_deleted: -              db->repos_only = TRUE; - -              if (!info->have_more_work) -                svn_hash_sets(pb->compared, -                              apr_pstrdup(pb->pool, db->name), ""); -              break; -            case svn_wc__db_status_added: -              if (eb->ignore_ancestry) -                db->ignoring_ancestry = TRUE; -              else +        { +          switch (info->status) +            { +              case svn_wc__db_status_normal: +              case svn_wc__db_status_incomplete: +                db->is_incomplete = (info->status == +                                     svn_wc__db_status_incomplete); +                break; +              case svn_wc__db_status_deleted:                  db->repos_only = TRUE; -              break; -            default: -              SVN_ERR_MALFUNCTION(); + +                if (!info->have_more_work) +                  svn_hash_sets(pb->compared, +                                apr_pstrdup(pb->pool, db->name), ""); +                break; +              case svn_wc__db_status_added: +                if (eb->ignore_ancestry) +                  db->ignoring_ancestry = TRUE; +                else +                  db->repos_only = TRUE; +                break; +              default: +                SVN_ERR_MALFUNCTION(); +          } + +          if (info->status == svn_wc__db_status_added +              || info->status == svn_wc__db_status_deleted) +            { +              svn_wc__db_status_t base_status; + +              /* Node is shadowed; check BASE */ +              SVN_ERR(svn_wc__db_base_get_info(&base_status, NULL, NULL, +                                               NULL, NULL, NULL, NULL, NULL, +                                               NULL, NULL, NULL, NULL, NULL, +                                               NULL, NULL, NULL, +                                               eb->db, db->local_abspath, +                                               dir_pool, dir_pool)); + +              if (base_status == svn_wc__db_status_incomplete) +                db->is_incomplete = TRUE; +            }          }        if (!db->repos_only) @@ -1714,7 +1835,7 @@ close_directory(void *dir_baton,      {        apr_hash_t *repos_props; -      if (db->added) +      if (db->added || db->is_incomplete)          {            repos_props = apr_hash_make(scratch_pool);          } @@ -1891,6 +2012,7 @@ open_file(const char *path,          switch (info->status)            {              case svn_wc__db_status_normal: +            case svn_wc__db_status_incomplete:                break;              case svn_wc__db_status_deleted:                fb->repos_only = TRUE; | 
