Skip to content

Commit fea4d88

Browse files
Francisco-Gaminomirichmo
authored andcommitted
Fixing update/save-help on Linux.
1 parent 7c30285 commit fea4d88

5 files changed

Lines changed: 97 additions & 13 deletions

File tree

src/System.Management.Automation/engine/InitialSessionState.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4595,7 +4595,12 @@ internal static string GetClearHostFunctionText()
45954595
else
45964596
{
45974597
// Porting note: non-Windows platforms use `clear`
4598-
return "& (Get-Command -CommandType Application clear | Select-Object -First 1).Definition";
4598+
return @"
4599+
& (Get-Command -CommandType Application clear | Select-Object -First 1).Definition
4600+
# .Link
4601+
# https://go.microsoft.com/fwlink/?LinkID=225747
4602+
# .ExternalHelp System.Management.Automation.dll-help.xml
4603+
";
45994604
}
46004605
}
46014606

src/System.Management.Automation/help/UpdatableHelpCommandBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ private void ProcessSingleModuleObject(PSModuleInfo module, ExecutionContext con
229229
}
230230
return;
231231
}
232-
if (!module.HelpInfoUri.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
232+
if (!(module.HelpInfoUri.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || module.HelpInfoUri.StartsWith("https://", StringComparison.OrdinalIgnoreCase)))
233233
{
234234
if (!noErrors)
235235
{

src/System.Management.Automation/help/UpdatableHelpModuleInfo.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ namespace System.Management.Automation.Help
1212
/// </summary>
1313
internal class UpdatableHelpModuleInfo
1414
{
15+
#if UNIX
16+
internal static readonly string HelpContentZipName = "HelpContent.zip";
17+
#else
1518
internal static readonly string HelpContentZipName = "HelpContent.cab";
19+
#endif
1620
internal static readonly string HelpIntoXmlName = "HelpInfo.xml";
1721

1822
/// <summary>

src/System.Management.Automation/help/UpdatableHelpSystem.cs

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
using Microsoft.PowerShell.Commands;
1818
using Microsoft.Win32;
1919
using System.Security;
20-
2120
#if CORECLR
21+
using System.IO.Compression;
2222
using System.Net.Http;
2323
using System.Threading.Tasks;
2424
// Use stub for SerializableAttribute, SerializationInfo and ISerializable related types. WebClient.
@@ -1209,9 +1209,9 @@ internal void InstallHelpContent(UpdatableHelpCommandType commandType, Execution
12091209
OnProgressChanged(this, new UpdatableHelpProgressEventArgs(CurrentModule, commandType, StringUtil.Format(
12101210
HelpDisplayStrings.UpdateProgressInstalling), 0));
12111211

1212-
string combinedSourcePath = Path.Combine(sourcePath, fileName);
1212+
string combinedSourcePath = GetFilePath(Path.Combine(sourcePath, fileName));
12131213

1214-
if (!File.Exists(combinedSourcePath))
1214+
if (string.IsNullOrEmpty(combinedSourcePath))
12151215
{
12161216
throw new UpdatableHelpSystemException("HelpContentNotFound", StringUtil.Format(HelpDisplayStrings.HelpContentNotFound),
12171217
ErrorCategory.ResourceUnavailable, null, null);
@@ -1249,6 +1249,37 @@ internal void InstallHelpContent(UpdatableHelpCommandType commandType, Execution
12491249
}
12501250
}
12511251

1252+
#if UNIX
1253+
private bool ExpandArchive(string source, string destination)
1254+
{
1255+
bool sucessfulDecompression = false;
1256+
1257+
try
1258+
{
1259+
using (FileStream archiveFileStream = new FileStream(source, IO.FileMode.Open, FileAccess.Read))
1260+
using (ZipArchive zipArchive = new ZipArchive(archiveFileStream, ZipArchiveMode.Read, false))
1261+
{
1262+
foreach (ZipArchiveEntry entry in zipArchive.Entries)
1263+
{
1264+
string extractPath = Path.Combine(destination, entry.FullName);
1265+
entry.ExtractToFile(extractPath);
1266+
}
1267+
sucessfulDecompression = true;
1268+
}
1269+
}
1270+
catch (ArgumentException) { }
1271+
catch (InvalidDataException) { }
1272+
catch (NotSupportedException) { }
1273+
catch (FileNotFoundException) { }
1274+
catch (IOException) { }
1275+
catch (SecurityException) { }
1276+
catch (UnauthorizedAccessException) { }
1277+
catch (ObjectDisposedException) { }
1278+
1279+
return sucessfulDecompression;
1280+
}
1281+
#endif
1282+
12521283
/// <summary>
12531284
/// Unzips to help content to a given location
12541285
/// </summary>
@@ -1265,20 +1296,25 @@ private void UnzipHelpContent(ExecutionContext context, string srcPath, string d
12651296
Directory.CreateDirectory(destPath);
12661297
}
12671298

1268-
string cabDir = Path.GetDirectoryName(srcPath);
1269-
1299+
string sourceDirectory = Path.GetDirectoryName(srcPath);
1300+
bool sucessfulDecompression = false;
1301+
#if UNIX
1302+
sucessfulDecompression = ExpandArchive(Path.Combine(sourceDirectory, Path.GetFileName(srcPath)), destPath);
1303+
#else
12701304
// Cabinet API doesn't handle the trailing back slash
1271-
if (!cabDir.EndsWith("\\", StringComparison.Ordinal))
1305+
if (!sourceDirectory.EndsWith("\\", StringComparison.Ordinal))
12721306
{
1273-
cabDir += "\\";
1307+
sourceDirectory += "\\";
12741308
}
12751309

12761310
if (!destPath.EndsWith("\\", StringComparison.Ordinal))
12771311
{
12781312
destPath += "\\";
12791313
}
1280-
1281-
if (!CabinetExtractorFactory.GetCabinetExtractor().Extract(Path.GetFileName(srcPath), cabDir, destPath))
1314+
1315+
sucessfulDecompression = CabinetExtractorFactory.GetCabinetExtractor().Extract(Path.GetFileName(srcPath), sourceDirectory, destPath);
1316+
#endif
1317+
if (!sucessfulDecompression)
12821318
{
12831319
throw new UpdatableHelpSystemException("UnableToExtract", StringUtil.Format(HelpDisplayStrings.UnzipFailure),
12841320
ErrorCategory.InvalidOperation, null, null);
@@ -1574,9 +1610,10 @@ internal static string LoadStringFromPath(PSCmdlet cmdlet, string path, PSCreden
15741610
}
15751611
}
15761612

1577-
if (File.Exists(path))
1613+
string filePath = GetFilePath(path);
1614+
if (!string.IsNullOrEmpty(filePath))
15781615
{
1579-
using (FileStream currentHelpInfoFile = new FileStream(path, FileMode.Open, FileAccess.Read))
1616+
using (FileStream currentHelpInfoFile = new FileStream(filePath, FileMode.Open, FileAccess.Read))
15801617
{
15811618
StreamReader reader = new StreamReader(currentHelpInfoFile);
15821619

@@ -1587,6 +1624,43 @@ internal static string LoadStringFromPath(PSCmdlet cmdlet, string path, PSCreden
15871624
return null;
15881625
}
15891626

1627+
/// <summary>
1628+
/// Validate the given path. If it exists, return the full path to the file.
1629+
/// </summary>
1630+
/// <param name="path"></param>
1631+
/// <returns></returns>
1632+
internal static string GetFilePath(string path)
1633+
{
1634+
#if UNIX
1635+
// On Linux, file paths are case sensitive.
1636+
// The user does not have control over the files (HelpInfo.xml, .zip, and cab) that are generated by the Publishing team.
1637+
// The logic below is to support updating help content via sourcepath parameter for case insensitive files.
1638+
FileInfo item = new FileInfo(path);
1639+
string directoryPath = item.Directory.FullName;
1640+
string fileName = item.Name;
1641+
1642+
// Prerequisite: The directory in the given path must exist and it is case sensitive.
1643+
if (Utils.NativeDirectoryExists(directoryPath))
1644+
{
1645+
// Get the list of files in the directory.
1646+
string[] fileList = Directory.GetFiles(directoryPath);
1647+
foreach (string filePath in fileList)
1648+
{
1649+
if (filePath.EndsWith(fileName, StringComparison.OrdinalIgnoreCase))
1650+
{
1651+
return filePath;
1652+
}
1653+
}
1654+
}
1655+
#else
1656+
if (Utils.NativeFileExists(path))
1657+
{
1658+
return path;
1659+
}
1660+
#endif
1661+
return null;
1662+
}
1663+
15901664
/// <summary>
15911665
/// Gets the default source path from GP
15921666
/// </summary>

src/System.Management.Automation/project.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@
161161
"System.IO.FileSystem.DriveInfo": "4.3.0-preview1-24530-04",
162162
"System.IO.FileSystem.Watcher": "4.3.0-preview1-24530-04",
163163
"System.IO.Pipes": "4.3.0-preview1-24530-04",
164+
"System.IO.Compression.ZipFile": "4.3.0-preview1-24530-04",
164165
"System.Linq.Expressions": "4.3.0-preview1-24530-04",
165166
"System.Net.Http": "4.3.0-preview1-24530-04",
166167
"System.Net.NetworkInformation": "4.3.0-preview1-24530-04",

0 commit comments

Comments
 (0)