private IList <FieldDesynchronization> GetFieldSyncStatus(SitecoreSourceItem item, ISerializedItem serializedItem, IFieldPredicate fieldPredicate)
        {
            var desyncs = new List <FieldDesynchronization>();

            var serializedVersion = serializedItem.Versions.FirstOrDefault(x => x.VersionNumber == item.InnerItem.Version.Number && x.Language == item.InnerItem.Language.Name);

            if (serializedVersion == null)
            {
                desyncs.Add(new FieldDesynchronization("Version"));
                return(desyncs);
            }

            item.InnerItem.Fields.ReadAll();

            foreach (Field field in item.InnerItem.Fields)
            {
                if (field.ID == FieldIDs.Revision ||
                    field.ID == FieldIDs.Updated ||
                    field.ID == FieldIDs.Created ||
                    field.ID == FieldIDs.CreatedBy ||
                    field.ID == FieldIDs.UpdatedBy ||
                    field.Type.Equals("attachment", StringComparison.OrdinalIgnoreCase) ||
                    !fieldPredicate.Includes(field.ID).IsIncluded)
                {
                    continue;
                }
                // we're doing a data comparison here - revision, created (by), updated (by) don't matter
                // skipping these fields allows us to ignore spurious saves the template builder makes to unchanged items being conflicts

                // find the field in the serialized item in either versioned or shared fields
                string serializedField;

                if (!serializedVersion.Fields.TryGetValue(field.ID.ToString(), out serializedField))
                {
                    serializedItem.SharedFields.TryGetValue(field.ID.ToString(), out serializedField);
                }

                // we ignore if the field doesn't exist in the serialized item. This is because if you added a field to a template,
                // that does not immediately re-serialize all items based on that template so it's likely innocuous - we're not overwriting anything.
                if (serializedField == null)
                {
                    continue;
                }

                if (!serializedField.Equals(field.Value, StringComparison.Ordinal))
                {
                    desyncs.Add(new FieldDesynchronization(field.Name));
                }
            }

            return(desyncs);
        }
        public void CopyItem(ItemDefinition source, ItemDefinition destination, string copyName, ID copyId, CallContext context)
        {
            if (DisableSerialization)
            {
                return;
            }

            // copying is easy - all we have to do is serialize the copyID. Copied children will all result in multiple calls to CopyItem so we don't even need to worry about them.
            var copiedItem = new SitecoreSourceItem(Database.GetItem(copyId));

            if (!_predicate.Includes(copiedItem).IsIncluded)
            {
                return;                                                          // destination parent is not in a path that we are serializing, so skip out
            }
            _serializationProvider.SerializeItem(copiedItem);
            _logger.CopiedItem(_serializationProvider.LogName, () => GetSourceFromDefinition(source), copiedItem);
        }
        private string GetErrorValue(SaveArgs args)
        {
            var results = new Dictionary <Item, IList <FieldDesynchronization> >();

            try
            {
                foreach (var item in args.Items)
                {
                    Item existingItem = Client.ContentDatabase.GetItem(item.ID, item.Language, item.Version);

                    Assert.IsNotNull(existingItem, "Existing item {0} did not exist! This should never occur.", item.ID);

                    var existingSitecoreItem = new SitecoreSourceItem(existingItem);

                    foreach (var configuration in _configurations)
                    {
                        // ignore conflicts on items that Unicorn is not managing
                        if (!configuration.Resolve <IPredicate>().Includes(existingSitecoreItem).IsIncluded)
                        {
                            continue;
                        }

                        ISerializedReference serializedReference = configuration.Resolve <ISerializationProvider>().GetReference(existingSitecoreItem);

                        if (serializedReference == null)
                        {
                            continue;
                        }

                        // not having an existing serialized version means no possibility of conflict here
                        ISerializedItem serializedItem = serializedReference.GetItem();

                        if (serializedItem == null)
                        {
                            continue;
                        }

                        var fieldPredicate = configuration.Resolve <IFieldPredicate>();

                        var fieldIssues = GetFieldSyncStatus(existingSitecoreItem, serializedItem, fieldPredicate);

                        if (fieldIssues.Count == 0)
                        {
                            continue;
                        }

                        results.Add(existingItem, fieldIssues);
                    }
                }

                // no problems
                if (results.Count == 0)
                {
                    return(null);
                }

                var sb = new StringBuilder();
                sb.Append("CRITICAL MESSAGE FROM UNICORN:\n");
                sb.Append("You need to run a Unicorn sync. The following fields did not match the serialized version:\n");

                foreach (var item in results)
                {
                    if (results.Count > 1)
                    {
                        sb.AppendFormat("\n{0}: {1}", item.Key.DisplayName, string.Join(", ", item.Value.Select(x => x.FieldName)));
                    }
                    else
                    {
                        sb.AppendFormat("\n{0}", string.Join(", ", item.Value.Select(x => x.FieldName)));
                    }
                }

                sb.Append("\n\nDo you want to overwrite anyway?\nTHIS MAY CAUSE LOST WORK.");

                return(sb.ToString());
            }
            catch (Exception ex)
            {
                Log.Error("Exception occurred while performing serialization conflict check!", ex, this);
                return("Exception occurred: " + ex.Message);                // this will cause a few retries
            }
        }