Пример #1
0
        /// <summary>
        /// Writes a set of scripts to the file system.
        /// </summary>
        /// <param name="scripts">The scripts to write out.</param>
        /// <param name="differences">The differences the scripts are based on.</param>
        public static void WriteScripts(ScriptSet scripts, DifferenceSet differences)
        {
            if (!Directory.Exists(RunOptions.Current.ScriptOutputDirectory))
            {
                Directory.CreateDirectory(RunOptions.Current.ScriptOutputDirectory);
            }

            StreamWriter writer = null;

            if (RunOptions.Current.ScriptFile != null)
            {
                writer = new StreamWriter(
                    Path.Combine(RunOptions.Current.ScriptOutputDirectory, RunOptions.Current.ScriptFile), false);

                if (differences != null)
                {
                    writer.WriteLine("/*");
                    writer.WriteLine("Changes:");
                    differences.Write(writer);
                    writer.WriteLine("*/");
                    writer.WriteLine();
                }

                writer.Write("SET NOCOUNT ON\n\nGO\n\n");
                writer.Write("SET QUOTED_IDENTIFIER ON\nGO\n\n");
            }

            StreamWriter diffWriter = null;

            if (RunOptions.Current.DiffFile != null)
            {
                writer = new StreamWriter(
                    Path.Combine(RunOptions.Current.ScriptOutputDirectory, RunOptions.Current.DiffFile), false);
            }

            for (int i = 0; i < scripts.Count; i++)
            {
                Script script = (Script)scripts[i];
                if (writer == null)
                {
                    string extension = ScriptExtensions.ContainsKey(script.Type) ? ScriptExtensions[script.Type] : ".sql";
                    writer = new StreamWriter(
                        Path.Combine(RunOptions.Current.ScriptOutputDirectory, script.Name.Unescaped + extension), false);
                }
                else
                {
                    writer.Write("-- " + i + " - " + script.Name + "\r\nGO\r\n");
                }
                writer.Write(script.Text);
                writer.Flush();
                if (RunOptions.Current.ScriptFile == null)
                {
                    writer.Close();
                    writer = null;
                }
                else
                {
                    writer.Write("\r\n\r\n");
                }
            }

            if (writer != null)
            {
                writer.Close();
            }
            if (diffWriter != null)
            {
                diffWriter.Close();
            }
        }
Пример #2
0
        /// <summary>
        /// Writes a difference summary to the file system.
        /// </summary>
        /// <param name="differences">The differences.</param>
        /// <param name="referenceDatabase">Reference database definition</param>
        /// <param name="targetDatabase">Target database to update</param>
        public static void WriteDifferenceSummary(DBTypes.Database referenceDatabase, DBTypes.Database targetDatabase, DifferenceSet differences)
        {
            StreamWriter diffWriter = new StreamWriter(Path.Combine(RunOptions.Current.ScriptOutputDirectory, RunOptions.Current.DiffFile), false);

            var patchGenerator = new DiffMatchPatch.diff_match_patch();

            foreach (var difference in differences)
            {
                if (difference.DifferenceType != DifferenceType.Modified)
                {
                    continue;
                }

                diffWriter.WriteLine(difference.ToString());
                diffWriter.WriteLine();

                var referenceDefinition = referenceDatabase[difference.Item].GenerateCreateScript();
                var targetDefinition    = targetDatabase[difference.Item].GenerateCreateScript();
                var diff = patchGenerator.diff_main(targetDefinition.Text, referenceDefinition.Text);
                //var patch = patchGenerator.diff_prettyHtml(diff);
                //patch = System.Web.HttpUtility.UrlDecode(patch);
                //diffWriter.WriteLine(patch);

                //Diffs aren't full lines...  we need to fix that for readability
                var coalesced = new List <DiffMatchPatch.Diff>();
                DiffMatchPatch.Diff lastEqual  = null;
                DiffMatchPatch.Diff lastInsert = null;
                DiffMatchPatch.Diff lastDelete = null;
                foreach (var entry in diff)
                {
                    if (entry.operation == DiffMatchPatch.Operation.INSERT)
                    {
                        lastInsert       = lastInsert ?? new DiffMatchPatch.Diff(entry.operation, "");
                        lastInsert.text += entry.text;
                    }
                    else if (entry.operation == DiffMatchPatch.Operation.DELETE)
                    {
                        lastDelete       = lastDelete ?? new DiffMatchPatch.Diff(entry.operation, "");
                        lastDelete.text += entry.text;
                    }
                    else if (entry.operation == DiffMatchPatch.Operation.EQUAL)
                    {
                        string content   = entry.text;
                        int    linebreak = content.IndexOf("\n");
                        string donate    = linebreak < 0 ? content : content.Substring(0, linebreak + 1);

                        //see if there's a change that needs this to finish its line
                        bool used = false;
                        if (lastInsert != null)
                        {
                            lastInsert.text += donate;
                            used             = true;
                        }
                        if (lastDelete != null)
                        {
                            lastDelete.text += donate;
                            used             = true;
                        }

                        if (used)
                        {
                            content = content.Remove(0, donate.Length);
                        }

                        //stash anything that's left
                        if (content.Length > 0)
                        {
                            //time to flush everything we've coalesced

                            //see if there are any mods that need to grab a line start
                            if (lastEqual != null && !lastEqual.text.EndsWith("\n") && (lastInsert != null || lastDelete != null))
                            {
                                linebreak      = lastEqual.text.LastIndexOf("\n");
                                donate         = lastEqual.text.Substring(linebreak + 1);
                                lastEqual.text = lastEqual.text.Remove(linebreak + 1);

                                if (lastInsert != null)
                                {
                                    lastInsert.text = donate + lastInsert.text;
                                }
                                if (lastDelete != null)
                                {
                                    lastDelete.text = donate + lastDelete.text;
                                }
                            }

                            //do the flush
                            if (lastEqual != null)
                            {
                                coalesced.Add(lastEqual);
                                lastEqual = null;
                            }
                            if (lastInsert != null)
                            {
                                coalesced.Add(lastInsert);
                                lastInsert = null;
                            }
                            if (lastDelete != null)
                            {
                                coalesced.Add(lastDelete);
                                lastDelete = null;
                            }

                            lastEqual = new DiffMatchPatch.Diff(DiffMatchPatch.Operation.EQUAL, content);
                        }
                    }
                    else
                    {
                        throw new Exception("Unknown operation: " + entry.operation);
                    }
                }
                if (lastEqual != null)
                {
                    coalesced.Add(lastEqual);
                }
                if (lastInsert != null)
                {
                    coalesced.Add(lastInsert);
                }
                if (lastDelete != null)
                {
                    coalesced.Add(lastDelete);
                }

                //Finally spit out a nice diff
                for (int i = 0; i < coalesced.Count; i++)
                {
                    var entry = coalesced[i];
                    if (entry.operation == DiffMatchPatch.Operation.EQUAL)
                    {
                        //(ab)use a stream to partition the content into lines
                        using (var text = new StreamReader(new MemoryStream(Encoding.UTF8.GetBytes(entry.text))))
                        {
                            //write out the first two lines
                            if (i > 0)
                            {
                                for (int j = 0; j < 2 && !text.EndOfStream; j++)
                                {
                                    string line = text.ReadLine();
                                    if (string.IsNullOrEmpty(line))
                                    {
                                        j--;
                                        continue;
                                    }

                                    diffWriter.WriteLine(line);
                                }
                            }

                            //write out the last two lines
                            if (i < coalesced.Count - 1 && !text.EndOfStream)
                            {
                                var lines = new string[3];
                                while (!text.EndOfStream)
                                {
                                    lines[0] = lines[1];
                                    lines[1] = lines[2];
                                    lines[2] = text.ReadLine();
                                }

                                if (i > 0 && lines[0] != null)
                                {
                                    diffWriter.WriteLine();
                                    diffWriter.WriteLine(">> ... <<");
                                    diffWriter.WriteLine();
                                }

                                if (lines[1] != null)
                                {
                                    diffWriter.WriteLine(lines[1]);
                                }
                                diffWriter.WriteLine(lines[2]);
                            }
                        }
                    }
                    else
                    {
                        string marker = entry.operation == DiffMatchPatch.Operation.INSERT ? "> > > >" : "< < < <";
                        diffWriter.WriteLine(marker);
                        diffWriter.Write(entry.text);
                        if (!entry.text.EndsWith("\n"))
                        {
                            diffWriter.WriteLine();
                        }
                        diffWriter.WriteLine(marker);
                    }
                }
                diffWriter.WriteLine();
            }

            diffWriter.Close();
        }