Click here to Skip to main content
15,892,298 members
Articles / Programming Languages / C#

Visual Studio .NET 2003 Add-in that adds diff tools, an explore command, Subversion support and web project reporting. Version 2.1

Rate me:
Please Sign up or sign in to vote.
4.88/5 (25 votes)
27 Jul 200528 min read 219.8K   2.8K   142  
With this add-in, you get new tools and commands that boost your productivity while developing and some helpful reports specially for web projects. Version 2.1.
using System;
using System.Collections;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Web;

using Extensibility;
using EnvDTE;

using my.utils; // the real diff-work is done there !

namespace WebReports {

  /// <summary>Generate a Patch file in unified patch format.</summary>
  internal class MakePatchFile : Report {

    /// <summary>Option name for the number of common lines arround differences.</summary>
    public const string PATCHEXTRALINES = "PatchExtraLines";

    /// <summary>Create a MakePatchFile object.</summary>
    public MakePatchFile() {
      WebReports.Options.DefineTextOption(PATCHEXTRALINES, "3");
    } // MakePatchFile


    /// <summary>Number of arguments this report needs to run.</summary>
    public override int Arguments {
      get { return (2); }
    }


    /// <summary>Generate an additional argument if needed.</summary>
    public override string AutoArgument(_DTE applicationObject, StringCollection cmdArgs) {
      if (cmdArgs.Count == 1)
        return (ccs.GetBaseFilename(cmdArgs[0]));
      return(null);
    } // AutoArgument


    /// <summary>Do the analysis by reading 2 files, compare them and render html to the output.</summary>
    /// <param name="applicationObject">reference to the VS.NET</param>
    /// <param name="output">ouput stream</param>
    /// <param name="args">List of all arguments passed to this command.</param>
    public override void Render(_DTE applicationObject, StringWriter output, params string[] args) {
      if (args.Length < 2)
        throw new ArgumentException(@"Select 2 files to compare.");

      string newFile = args[0];
      string oldFile = args[1];
      string outfile = null;

      if ((oldFile == null) || (newFile == null))
        throw new ArgumentException(@"Select 2 files to compare.");

      string opts = Options.GetTextOption(ReportDiffFiles.DIFFOPTIONS);
      for (int c = 2; c < args.Length; c++) {
        string arg = args[c].Trim().ToLower();
        if (arg.StartsWith("/"))
          opts = arg;
        else 
          outfile = arg;
      } // for

      string patchText = GenerateUnifiedPatch(oldFile, newFile, opts, Options.GetTextOption(PATCHEXTRALINES));

      string html = ExtractHtmlResource("WebReports.WebReports.MakePatchFile.htm");

      html = html.Replace("[OLDFILE]", System.Web.HttpUtility.HtmlEncode(oldFile));
      html = html.Replace("[OLDFILEENC]", System.Web.HttpUtility.UrlEncode(oldFile));
      html = html.Replace("[NEWFILE]", System.Web.HttpUtility.HtmlEncode(newFile));
      html = html.Replace("[NEWFILEENC]", System.Web.HttpUtility.UrlEncode(newFile));

      // write the starting html
      output.Write(html.Substring(0, html.IndexOf("[RESULT]")));
      output.Write(patchText);

      // write the end html
      output.Write(html.Substring(html.IndexOf("[RESULT]")+8));

      // open a outfile
//      if (outfile != null)
      // File.CreateText(outfile);

    } // Render


    /// <summary>Do the analysis by reading 2 files, compare them and generate a text containing a unified diff.</summary>
    /// <param name="oldFile">path to the original, old file.</param>
    /// <param name="newFile">Path to the modified, new file.</param>
    /// <param name="diffOpts">Options used to find the differences in the text.</param>
    /// <param name="patchOpts">Option to the unified diff format: the number of equal lines around modified lines.</param>
    public string GenerateUnifiedPatch(string oldFile, string newFile, string diffOpts, string patchOpts) {
      if (oldFile == null)
        throw new ArgumentNullException("oldFile");
      if (newFile == null)
        throw new ArgumentNullException("newFile");

      string a, b;
      StreamReader aFile;

      aFile = File.OpenText(oldFile);
      a = aFile.ReadToEnd();
      aFile.Close();

      aFile = File.OpenText(newFile);
      b = aFile.ReadToEnd();
      aFile.Close();

      Diff d = new Diff();
      Diff.Item [] f = d.DiffText(a, b,
        (diffOpts.IndexOf("/t") >= 0), (diffOpts.IndexOf("/s") >= 0), (diffOpts.IndexOf("/c") >= 0), (diffOpts.IndexOf("/w") >= 0));
      string[]aLines = a.Split('\n');
      string[]bLines = b.Split('\n');

      // number of common lines arround differences
      int extraLines = int.Parse(patchOpts);
      if (extraLines == 0) extraLines = 3;
            
      int n = 0; // LineCounter in the old (A) file
      int l;

      StringBuilder sb = new StringBuilder(); // output of the diff-lines
      StringBuilder patchText = new StringBuilder(); // complete patch text
      int blockOldStart = -1;
      int blockNewStart = -1;

      for (int fdx = 0; fdx < f.Length; fdx++) {
        Diff.Item aItem = f[fdx];

        // real different lines
        int oldStart = aItem.StartA;
        int newStart = aItem.StartB;

        // add common lines at the beginning
        if (oldStart - extraLines >= n) {
          oldStart -= extraLines;
          newStart -= extraLines;
        } else {
          l = oldStart - n;
          oldStart -= l;
          newStart -= l;
        } // if

        if (blockOldStart == -1) {
          blockOldStart = oldStart;
          blockNewStart = newStart;
        } // if
        
        for (l = oldStart; l < aItem.StartA; l++)
          sb.AppendFormat("{0}{1}\n", " ", System.Web.HttpUtility.HtmlEncode(aLines[l]));

        // write deleted lines
        for (l = aItem.StartA; l < aItem.StartA + aItem.deletedA; l++)
          sb.AppendFormat("{0}{1}\n", "-", System.Web.HttpUtility.HtmlEncode(aLines[l]));

        // write inserted lines
        for (l = aItem.StartB; l < aItem.StartB + aItem.insertedB; l++)
          sb.AppendFormat("{0}{1}\n", "+", System.Web.HttpUtility.HtmlEncode(bLines[l]));

        n = aItem.StartA + aItem.deletedA; 

        // write trailing common lines
        l = Math.Min(aLines.Length, n + extraLines);
        while (n < l) {
          sb.AppendFormat("{0}{1}\n", "&nbsp;", System.Web.HttpUtility.HtmlEncode(aLines[n]));
          n++;
        } // while

        // if this was the last block
        // or if next different part is far away then finish this block of changes
        if ((fdx == f.Length-1) || (n < f[fdx+1].StartA - 2 * extraLines)) {
          patchText.Append(
            "@@ -" + (blockOldStart+1).ToString() + "," + (n - blockOldStart).ToString()
            + " +"   + (blockNewStart+1).ToString() + "," + (aItem.StartB + aItem.insertedB - blockNewStart + n - (aItem.StartA + aItem.deletedA) ).ToString()
            + " @@\n");
          patchText.Append(sb.ToString());
          sb = new StringBuilder();
          blockOldStart = -1;
        } // if
      } // for

      return(patchText.ToString());
    } // GenerateUnifiedPatch
  
  
  } // class

} // namespace

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Deutsche Bank AG
Germany Germany
see https://www.mathertel.de

Comments and Discussions