#region CPL License /* Nuclex.NAnt.Tasks Copyright (C) 2009 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using Microsoft.Win32; namespace Nuclex.NAnt.Tasks.Helpers { /// Locates the subversion executable on the system public static class SubversionLocator { /// Tries to locate the Subversion executable on the current system /// /// You do not need to call this normally. The 'Location' property will /// automatically initiate a search the first time it is called. Only call /// this method if you suspect the system might have changed and wish to /// rescan for the Subversion executable. /// public static void Locate() { if(OsHelper.IsWindows) { location = findUsingRegistry(); if(location == null) { location = findOnWindows(); } } else { location = findOnUnix(); } locationAttempted = true; } /// The location of the Subversion executable or null if not found /// /// Will search for Subversion on the system the first time it is called, so it /// may block for a moment before returning. /// public static string Location { get { if(!locationAttempted) { Locate(); } return location; } } /// Tries to locate subversion using a file search on windows /// The directory the subversion executable can be found in or null private static string findOnWindows() { Debug.Assert(OsHelper.IsWindows); if(EnvironmentHelper.RunningOn64BitOS) { string location = searchWindowsProgramFilesFolder(KnownFolders.ProgramFiles64Path); if(location != null) { return location; } } return searchWindowsProgramFilesFolder(KnownFolders.ProgramFiles32Path); } /// Searches the program files folder for a Subversion executable /// The path to the Subversion executable or null if not found private static string searchWindowsProgramFilesFolder(string programFilesFolder) { string location = searchWindowsSubversionDistribution( programFilesFolder, "CollabNet Subversion*" ); if(location == null) { location = searchWindowsSubversionDistribution( programFilesFolder, "SlikSvn*" ); } return location; } /// Searches for an installed Subversion distribution on windows /// Path of the program files folder /// Mark of the directories that will be checked /// The directory of the subversion executable, if found private static string searchWindowsSubversionDistribution( string programFilesFolder, string folderMask ) { string[] subversionFolders = Directory.GetDirectories( programFilesFolder, folderMask ); for(int index = 0; index < subversionFolders.Length; ++index) { string potentialLocation = Path.Combine(subversionFolders[index], "svn.exe"); if(File.Exists(potentialLocation)) { return potentialLocation; } potentialLocation = Path.Combine(subversionFolders[index], @"bin\svn.exe"); if(File.Exists(potentialLocation)) { return potentialLocation; } } return null; } /// Tries to locate a subversion executable using the registry /// The path to the subversion installation folder or null private static string findUsingRegistry() { string location = tryCollabNetSvnFromRegistry(); if(location == null) { location = trySlikSvnFromRegistry(); } return location; } /// Tries to locate SlikSvn using its registry path /// The path to the SlikSvn installation folder or null if not found private static string trySlikSvnFromRegistry() { using( RegistryKey slikSvnKey = Registry.LocalMachine.OpenSubKey( @"SOFTWARE\SlikSvn\Install" ) ) { if(slikSvnKey == null) { return null; } string folder = (string)slikSvnKey.GetValue("Location"); if(Directory.Exists(folder)) { string potentialLocation = Path.Combine(folder, "svn.exe"); if(File.Exists(potentialLocation)) { return potentialLocation; } } } return null; } /// Tries to locate CollabNet Subversion using the registry /// The installation folder of CollabNet Subversion or null private static string tryCollabNetSvnFromRegistry() { using( RegistryKey collabNetKey = Registry.LocalMachine.OpenSubKey( @"SOFTWARE\CollabNet\Subversion" ) ) { if(collabNetKey == null) { return null; } string[] versionKeyNames = collabNetKey.GetSubKeyNames(); for(int index = versionKeyNames.Length - 1; index >= 0; --index) { using( RegistryKey versionKey = collabNetKey.OpenSubKey(versionKeyNames[index]) ) { string location = tryCollabNetSvnPath(versionKey, "Client"); if(location == null) { location = tryCollabNetSvnPath(versionKey, "Server"); } if(location != null) { return location; } } } // for each version key } return null; } /// Checks one of the specific CollabNet release type keys /// Version key under the CollabNet main key /// /// Which type of release to check (either "Client" or "Server") /// /// The path to the subversion installation folder or null private static string tryCollabNetSvnPath(RegistryKey versionKey, string type) { using(RegistryKey serverKey = versionKey.OpenSubKey(type)) { if(serverKey == null) { return null; } string folder = (string)serverKey.GetValue("Install Location"); if(Directory.Exists(folder)) { string potentialLocation = Path.Combine(folder, "svn.exe"); if(File.Exists(potentialLocation)) { return potentialLocation; } } } return null; } /// Tries to locate 7-Zip in its default path on a unix system /// The path to the 7-Zip executable or null if not found private static string findOnUnix() { Debug.Assert(OsHelper.IsUnix); string subversionPath = "/usr/local/bin/svn"; if(File.Exists(subversionPath)) { return subversionPath; } subversionPath = "/usr/bin/svn"; if(File.Exists(subversionPath)) { return subversionPath; } subversionPath = "/bin/svn"; if(File.Exists(subversionPath)) { return subversionPath; } return null; } /// whether we attempted to locate Subversion already private static volatile bool locationAttempted; /// The location of the Subversion executable or null private static string location; } } // namespace Nuclex.NAnt.Tasks.Helpers