forked from KSP-CKAN/CKAN-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
KSPPathUtils.cs
239 lines (199 loc) · 7.64 KB
/
KSPPathUtils.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
using System;
using System.IO;
using System.Text.RegularExpressions;
using log4net;
namespace CKAN
{
public class KSPPathUtils
{
private static readonly ILog log = LogManager.GetLogger(typeof(KSPPathUtils));
/// <summary>
/// Finds Steam on the current machine.
/// </summary>
/// <returns>The path to Steam, or null if not found</returns>
public static string SteamPath()
{
// First check the registry.
const string reg_key = @"HKEY_CURRENT_USER\Software\Valve\Steam";
const string reg_value = @"SteamPath";
log.DebugFormat("Checking {0}\\{1} for Steam path", reg_key, reg_value);
var steam = (string)Microsoft.Win32.Registry.GetValue(reg_key, reg_value, null);
// If that directory exists, we've found Steam!
if (steam != null && Directory.Exists(steam))
{
log.InfoFormat("Found Steam at {0}", steam);
return steam;
}
log.Debug("Couldn't find Steam via registry key, trying other locations...");
// Not in the registry, or missing file, but that's cool. This should find it on Linux
steam = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
".local",
"share",
"Steam"
);
log.DebugFormat("Looking for Steam in {0}", steam);
if (Directory.Exists(steam))
{
log.InfoFormat("Found Steam at {0}", steam);
return steam;
}
// Try an alternative path.
steam = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
".steam",
"steam"
);
log.DebugFormat("Looking for Steam in {0}", steam);
if (Directory.Exists(steam))
{
log.InfoFormat("Found Steam at {0}", steam);
return steam;
}
// Ok - Perhaps we're running OSX?
steam = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.Personal),
Path.Combine("Library", "Application Support", "Steam")
);
log.DebugFormat("Looking for Steam in {0}", steam);
if (Directory.Exists(steam))
{
log.InfoFormat("Found Steam at {0}", steam);
return steam;
}
log.Info("Steam not found on this system.");
return null;
}
/// <summary>
/// Finds the KSP path under Steam. Returns null if the folder cannot be located.
/// </summary>
/// <returns>The KSP path.</returns>
public static string KSPSteamPath()
{
// Attempt to get the Steam path.
string steam_path = SteamPath();
if (steam_path == null)
{
return null;
}
// There are several possibilities for the path under Linux.
// Try with the uppercase version.
string ksp_path = Path.Combine(steam_path, "SteamApps", "common", "Kerbal Space Program");
if (Directory.Exists(ksp_path))
{
return ksp_path;
}
// Try with the lowercase version.
ksp_path = Path.Combine(steam_path, "steamapps", "common", "Kerbal Space Program");
if (Directory.Exists(ksp_path))
{
return ksp_path;
}
// Could not locate the folder.
return null;
}
/// <summary>
/// Normalizes the path by replace any \ with / and removing any trailing slash.
/// </summary>
/// <returns>The normalized path.</returns>
/// <param name="path">The path to normalize.</param>
public static string NormalizePath(string path)
{
return path.Replace('\\', '/').TrimEnd('/');
}
/// <summary>
/// Gets the last path element. Ex: /a/b/c returns c
/// </summary>
/// <returns>The last path element.</returns>
/// <param name="path">The path to process.</param>
public static string GetLastPathElement(string path)
{
return Regex.Replace(NormalizePath(path), @"^.*/", "");
}
/// <summary>
/// Gets the leading path elements. Ex: /a/b/c returns /a/b
///
/// Returns empty string if there is no leading path. (Eg: "Example.dll" -> "");
/// </summary>
/// <returns>The leading path elements.</returns>
/// <param name="path">The path to process.</param>
public static string GetLeadingPathElements(string path)
{
path = NormalizePath(path);
if (Regex.IsMatch(path, "/"))
{
return Regex.Replace(path, @"(^.*)/.+", "$1");
}
return String.Empty;
}
/// <summary>
/// Converts a path to one relative to the root provided.
/// Please use KSP.ToRelative when working with gamedirs.
/// Throws a PathErrorKraken if the path is not absolute, not inside the root,
/// or either argument is null.
/// </summary>
public static string ToRelative(string path, string root)
{
if (path == null || root == null)
{
throw new PathErrorKraken(null, "Null path provided");
}
// We have to normalise before we check for rootedness,
// otherwise backslash separators fail on Linux.
path = NormalizePath(path);
root = NormalizePath(root);
if (!Path.IsPathRooted(path))
{
throw new PathErrorKraken(
path,
String.Format("{0} is not an absolute path", path)
);
}
if (! path.StartsWith(root))
{
throw new PathErrorKraken(
path,
String.Format(
"Oh snap. {0} isn't inside {1}",
path, root
)
);
}
// The +1 here is because root will never have
// a trailing slash.
return path.Remove(0, root.Length + 1);
}
/// <summary>
/// Returns root/path, but checks that root is absolute,
/// path is relative, and normalises everything for great justice.
/// Please use KSP.ToAbsolute if converting from a KSP gamedir.
/// Throws a PathErrorKraken if anything goes wrong.
/// </summary>
public static string ToAbsolute(string path, string root)
{
if (path == null || root == null)
{
throw new PathErrorKraken(null, "Null path provided");
}
path = NormalizePath(path);
root = NormalizePath(root);
if (Path.IsPathRooted(path))
{
throw new PathErrorKraken(
path,
String.Format("{0} is already absolute", path)
);
}
if (!Path.IsPathRooted(root))
{
throw new PathErrorKraken(
root,
String.Format("{0} isn't an absolute root", root)
);
}
// Why normalise it AGAIN? Because Path.Combine can insert
// the un-prettiest slashes.
return NormalizePath(Path.Combine(root, path));
}
}
}