Index: sync/engine/syncer_util.cc |
diff --git a/sync/engine/syncer_util.cc b/sync/engine/syncer_util.cc |
index 7f63b37ddbdeeeb0a654b54a12ef6a597b67e34a..d97f34cc17039bcef680b6606ed185f905d95220 100644 |
--- a/sync/engine/syncer_util.cc |
+++ b/sync/engine/syncer_util.cc |
@@ -184,7 +184,23 @@ syncable::Id FindLocalIdToUpdate( |
return local_entry.GetId(); |
} |
+ } else if (update.has_server_defined_unique_tag() && |
+ !update.server_defined_unique_tag().empty()) { |
+ // The client creates type root folders on demand with a local ID on |
Nicolas Zea
2015/01/26 23:21:53
nit: "on demand with a local id on demand"?
stanisc
2015/01/29 00:27:37
Done.
|
+ // demand when a progress marker for the given type is initially set. |
+ // The server might also attempt to send a type root folder for the same |
+ // type. It will does that during the transition period until support for |
Nicolas Zea
2015/01/26 23:21:53
nit: " will does"
stanisc
2015/01/29 00:27:37
Done.
|
+ // root folders is removed on the server for most types. After that the |
+ // server will still be creating type root folders for BOOKMARKS and |
+ // NIGORI types. |
+ syncable::Entry local_entry(trans, syncable::GET_BY_SERVER_TAG, |
+ update.server_defined_unique_tag()); |
+ if (local_entry.good() && !local_entry.GetId().ServerKnows()) { |
+ DCHECK(local_entry.GetId() != update_id); |
+ return local_entry.GetId(); |
+ } |
} |
+ |
// Fallback: target an entry having the server ID, creating one if needed. |
return update_id; |
} |
@@ -227,16 +243,24 @@ UpdateAttemptResponse AttemptToUpdateEntry( |
if (!entry->GetServerIsDel()) { |
syncable::Id new_parent = entry->GetServerParentId(); |
- Entry parent(trans, GET_BY_ID, new_parent); |
- // A note on non-directory parents: |
- // We catch most unfixable tree invariant errors at update receipt time, |
- // however we deal with this case here because we may receive the child |
- // first then the illegal parent. Instead of dealing with it twice in |
- // different ways we deal with it once here to reduce the amount of code and |
- // potential errors. |
- if (!parent.good() || parent.GetIsDel() || !parent.GetIsDir()) { |
- DVLOG(1) << "Entry has bad parent, returning conflict_hierarchy."; |
- return CONFLICT_HIERARCHY; |
+ if (!new_parent.IsNull()) { |
+ // Perform this step only if the parent is specified. |
+ // The unset parent means that the implicit type root would be used. |
+ Entry parent(trans, GET_BY_ID, new_parent); |
+ // A note on non-directory parents: |
+ // We catch most unfixable tree invariant errors at update receipt time, |
+ // however we deal with this case here because we may receive the child |
+ // first then the illegal parent. Instead of dealing with it twice in |
+ // different ways we deal with it once here to reduce the amount of code |
+ // and |
+ // potential errors. |
Nicolas Zea
2015/01/26 23:21:53
nit: move to previous line
stanisc
2015/01/29 00:27:37
Done.
|
+ if (!parent.good() || parent.GetIsDel() || !parent.GetIsDir()) { |
+ DVLOG(1) << "Entry has bad parent, returning conflict_hierarchy."; |
+ return CONFLICT_HIERARCHY; |
+ } |
+ } else { |
+ DCHECK( |
+ !IsTypeWithServerGeneratedRoot(GetModelTypeFromSpecifics(specifics))); |
} |
if (entry->GetParentId() != new_parent) { |
if (!entry->GetIsDel() && !IsLegalNewParent(trans, id, new_parent)) { |