Encode Invalid characters in Visual SourceSafe file names.

Some time ago I had to create the utility to rename files with special characters to allow them to be inclyuded in Visual SourceSafe
I’ve used  VBeXpress generator, that had  templates with ‘%’ in file names. Unfortunately the names with ‘%’ like %%Project.Name%%.sln are not acceptable by VSS due to invalid VSS syntax.  This utility copies changed templates to files with encoded names,acceptable by VSS. It’s allowed to check-in/check out individual files(with encoded names) and view thier changes/history.

See the source code of utility file  EncodeInvalidVSSFileNames.dnml :

<dnml>

<!–This file can be run using DotNetScriptEngine.exe from http://www.codeproject.com/dotnet/DotNetScript.asp    –>

<!–Author Michael Freidgeim

    Created 17/8/2004

–>

<reference assembly=System.XML.dll />

<reference assembly=System.Windows.Forms.dll />

<reference assembly=System.Data.dll />

 

<language name=C# />

 

<scriptCode><![CDATA[

using System;

using System.IO;

namespace ValidVSSFileNames

{

      /// <summary>

      /// THe VBeXpress generation templates use ‘%’ in file names.

      /// Unfortunately the names with ‘%’ like %%Project.Name%%.sln  are not acceptable by VSS due to invalid VSS syntax.

      /// This class copies changed templates to files with encoded names,acceptable by VSS.

      /// It’s allowed to check-in/check out individual files(with encoded names) and view thier changes/history.

      /// </summary>

      /// <remarks>

      /// Current version doesn’t check out files, only reports if target file is read-only.

      /// </remarks>

      class ValidVSSFileNames

      {

            static char[] m_InvalidChars= new char[]{‘$’,’@’,'<‘,’>’,'{‘,’}’,'(‘,’)’,’:’,’;’,’=’,’^’,’|’,’*’,’!’,’/’,’\’,’%’,’?’,’,’,”’,'”‘,’t’};

       //mk:@MSITStore:C:Program%20FilesMicrosoft%20Visual%20StudioVSSSSUSEXP.CHM::/html/ssugrnaming_syntax_conventions_and_limitations.htm

            /*          Dollar sign ($)

                        At sign (@)

            Angle brackets (< >), brackets ([ ]), braces ({ }), and parentheses (( ))

            Colon (:) and semicolon (;)

            Equal sign (=)

            Caret sign (^)

            Pipe (vertical bar) (|)

            Asterisk (*)

            Exclamation point (!)

            Forward (/) and backward slash ()

            Percent sign (%)

            Question mark (?)

            Comma (,)

            Quotation mark (single or double) (‘ “)

                        Tab

            */

 

            /// <summary>

            /// The main entry point for the application.

            /// </summary>

            //[STAThread]

            public static int Main()//string[] args)

            {

//                Console.WriteLine(“Start”);       

                  int nRet=0;

//                if(args.Length>0) return nRet=ProcessArgs(args);

//            else

                  Console.WriteLine(“Start in ” + Environment.CurrentDirectory);        

                    ProcessDirectory(Environment.CurrentDirectory );

//                Console.WriteLine(“Press enter to close the application”);       

//                Console.ReadLine();       

                  return nRet;

            }

            /// <summary>

            /// The Process Arguments of command Line

            /// </summary>

            static int ProcessArgs(string[] args)

            {

                  foreach(string path in args)

                  {

                        if(File.Exists(path))

                        {

                              // This path is a file

                              ProcessFile(path);

                        }              

                        else if(Directory.Exists(path))

                        {

                              // This path is a directory

                              ProcessDirectory(path);

                        }

                        else

                        {

                              Console.WriteLine(“{0} is not a valid file or directory.”, path);

                        }       

                  }       

                  return 0;

            }

            /// <summary>

            /// Renames Files that have names with invalid in VSS characters(almost all non-alphanumeric)

            /// Process all files in the directory passed in, recurse on any directories

            /// that are found, and process the files they contain.

            /// </summary>

            //static Function RenameVSSInvalidFileNames(string dirPath)

            public static void ProcessDirectory(string targetDirectory)

            {

                  // Process the list of files found in the directory.

                  string [] fileEntries = Directory.GetFiles(targetDirectory);

                  foreach(string fileName in fileEntries)

                        ProcessFile(fileName);

 

                  // Recurse into subdirectories of this directory.

                  string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);

                  foreach(string subdirectory in subdirectoryEntries)

                        ProcessDirectory(subdirectory);

            }

        

            // Insert logic for processing found files here.

            public static void ProcessFile(string path)

            {

                        FileInfo fi= new FileInfo(path);

                  string dirPath=fi.Directory.FullName ;

                  if (IsEncodingRequired(fi.Name))

                  {

                              string EncodedName=EncodeName(fi.Name);

                        string pathEncoded=Path.Combine(dirPath,EncodedName);

                        if (File.Exists(pathEncoded))

                        {

                              FileInfo fiEncoded= new FileInfo(pathEncoded);

                              if( fi.LastWriteTime>fiEncoded.LastWriteTime)

                              {

                                    if ((fiEncoded.Attributes & FileAttributes.ReadOnly)==FileAttributes.ReadOnly)

                                    {

                                          Console.WriteLine(” file ‘{0}’ is read only. Check out for processing”, pathEncoded);       

                                    }

                                    else

                                    {

                                          fi.CopyTo (pathEncoded,true);

                                          Console.WriteLine(“Processed file ‘{0}’ into ‘{1}’.”, fi.Name,EncodedName);       

                                    }

                              }

                        }

                        else

                        {

                              fi.CopyTo (pathEncoded,false);

                              Console.WriteLine(“Processed file ‘{0}’ into ‘{1}’.”, fi.Name,EncodedName);       

                        }

                  }

            }

 

            /// <summary>

            /// Checks if name has invalid in VSS characters(almost all non-alphanumeric except ‘_’ )

            /// </summary>

            static bool IsEncodingRequired(string FileName)

            {

                  if ( FileName.IndexOfAny(m_InvalidChars) >=0 ) return true;

                  return false;

            }                                                                                                                                        

            /// <summary>

            ///Encoding is similar to  XmlConvert.EncodeName Method  help://MS.VSCC.2003/MS.MSDNQTR.2003FEB.1033/cpref/html/frlrfsystemxmlxmlconvertclassencodenametopic.htm

            ///it uses _xHHHH_ escaping

            /// </summary>

            /// <summary>

            /// Renames names with invalid in VSS characters(almost all non-alphanumeric except ‘_’ )

            /// </summary>

            static string EncodeName(string FileName)

            {

                  string sRet=FileName;

                  if (IsEncodingRequired( FileName))

                  {

                        foreach (char ch in m_InvalidChars)

                        {

                              sRet=sRet.Replace(ch.ToString() , “_x” +((int)ch).ToString(“X4”) + “_”) ;

                        }

                  }                                                                                                                                        

                  return sRet;

            }

      }

}

 

 

]]></scriptCode>

 

</dnml>