Add support for file overwriting in shell

This commit is contained in:
Jet the Hawk 2023-02-22 18:34:19 -05:00
parent b369e0f212
commit 0d8ed59f2c
7 changed files with 111 additions and 12 deletions

View file

@ -76,7 +76,7 @@ namespace OS.FileSystems.Host
{
string fullPath = Path.Combine(hostPath, name);
if (!File.Exists(fullPath))
File.Create(fullPath);
File.Create(fullPath).Dispose();
entry = new HostFileEntry(this, fullPath);
return true;

View file

@ -86,7 +86,7 @@ namespace OS.FileSystems
return currentEntry;
}
private IFileEntry? FindFileEntry(ReadOnlySpan<string> path, IUser? reader = null)
private IFileEntry? FindFileEntry(ReadOnlySpan<string> path, IUser? reader = null, bool create = false)
{
reader ??= this.user;
@ -105,7 +105,10 @@ namespace OS.FileSystems
if (fileEntry.Name == filename)
return fileEntry;
}
if (create && parentDirectory.TryCreateFile(reader, filename, out IFileEntry? newFile) && newFile != null)
return newFile;
return null;
}
@ -178,7 +181,7 @@ namespace OS.FileSystems
public Stream OpenWrite(string path)
{
string[] parts = PathUtility.Split(path);
IFileEntry? file = FindFileEntry(parts);
IFileEntry? file = FindFileEntry(parts, create: true);
if (file == null)
throw new FileNotFoundException();

View file

@ -0,0 +1,50 @@
#nullable enable
using System;
using System.IO;
using OS.Devices;
namespace UI.Shell
{
public class FileOutputConsole :
ITextConsole,
IDisposable
{
private readonly ITextConsole input;
private readonly Stream fileStream;
private readonly StreamWriter fileWriter;
public FileOutputConsole(ITextConsole input, Stream output)
{
this.input = input;
this.fileStream = output;
this.fileWriter = new StreamWriter(fileStream);
}
public void Dispose()
{
fileWriter.Dispose();
fileStream.Dispose();
}
/// <inheritdoc />
public void ClearScreen()
{
fileWriter.Flush();
fileStream.Position = 0;
fileStream.SetLength(0);
}
/// <inheritdoc />
public void WriteText(string text)
{
fileWriter.Write(text);
}
/// <inheritdoc />
public bool TryDequeueSubmittedInput(out string input)
{
return this.input.TryDequeueSubmittedInput(out input);
}
}
}

View file

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9a4a394e1f59409ca8bd9be2c65f373f
timeCreated: 1677107497

View file

@ -5,5 +5,8 @@ namespace UI.Shell
{
string GetVariableValue(string name);
void SetVariableValue(string name, string newValue);
string CurrentWorkingDirectory { get; }
string CurrentHomeDirectory { get; }
}
}

View file

@ -34,6 +34,13 @@ namespace UI.Shell
/// <inheritdoc />
public bool IsExecutionHalted => false;
/// <inheritdoc />
public string CurrentWorkingDirectory => process?.WorkingDirectory ?? "/";
/// <inheritdoc />
public string CurrentHomeDirectory => process?.User?.Home ?? "/";
public InteractiveShell(MonoBehaviour unityBehaviour)
{
this.unityBehaviour = unityBehaviour;
@ -487,6 +494,11 @@ namespace UI.Shell
public IArgumentEvaluator[] ArgumentList { get; }
public FileRedirectionType RedirectionType { get; }
public string FilePath { get; }
public string FullFilePath
{
get => PathUtility.Combine(shell.CurrentWorkingDirectory, FilePath);
}
public CommandData(InteractiveShell shell,string name, IEnumerable<IArgumentEvaluator> argumentSource, FileRedirectionType redirectionType, string path)
{
@ -534,23 +546,51 @@ namespace UI.Shell
// Evaluate arguments now.
string[] args = ArgumentList.Select(x => x.GetArgumentText(this.shell)).ToArray();
// TODO: File redirection. Should be easy.
if (shell.ProcessBuiltIn(shellProcess, console, Name, args))
// Get the vfs
var vfs = shellProcess.User.Computer.GetFileSystem(shellProcess.User);
// What console are we going to send to the command?
ITextConsole realConsole = console;
switch (this.RedirectionType)
{
case FileRedirectionType.Overwrite:
realConsole = new FileOutputConsole(console, vfs.OpenWrite(this.FullFilePath));
break;
}
if (shell.ProcessBuiltIn(shellProcess, realConsole, Name, args))
{
if (realConsole is IDisposable disposable)
disposable.Dispose();
return null;
}
// Process text arguments to make sure we remove their trailing spaces
ShellUtility.TrimTrailingSpaces(ref args);
ISystemProcess? commandProcess = FindProgram(shellProcess, console, Name, args);
ISystemProcess? commandProcess = FindProgram(shellProcess, realConsole, Name, args);
if (commandProcess == null)
console.WriteText($"sh: {Name}: command not found" + Environment.NewLine);
// special case for commands that kill the process IMMEDIATELY
// on the same frame this was called
if (commandProcess != null && !commandProcess.IsAlive)
{
if (realConsole is IDisposable disposable)
disposable.Dispose();
return null;
}
void handleKilled(ISystemProcess proc)
{
if (realConsole is IDisposable disposable)
disposable.Dispose();
proc.Killed -= handleKilled;
}
if (commandProcess != null)
commandProcess.Killed += handleKilled;
return commandProcess;
}
}

View file

@ -24,7 +24,7 @@ MonoBehaviour:
m_MinSize: {x: 300, y: 200}
m_MaxSize: {x: 24288, y: 16192}
vertical: 0
controlID: 5913
controlID: 7072
--- !u!114 &2
MonoBehaviour:
m_ObjectHideFlags: 52
@ -141,7 +141,7 @@ MonoBehaviour:
m_MinSize: {x: 200, y: 200}
m_MaxSize: {x: 16192, y: 16192}
vertical: 1
controlID: 5914
controlID: 7073
--- !u!114 &4
MonoBehaviour:
m_ObjectHideFlags: 52
@ -166,7 +166,7 @@ MonoBehaviour:
m_MinSize: {x: 200, y: 100}
m_MaxSize: {x: 16192, y: 8096}
vertical: 0
controlID: 5915
controlID: 7074
--- !u!114 &5
MonoBehaviour:
m_ObjectHideFlags: 52
@ -226,7 +226,7 @@ MonoBehaviour:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
m_LastClickedID: 0
m_ExpandedIDs: 30fbffff
m_ExpandedIDs: b0c7fefffcc7feff40c9feff50c9feff5cc9feff80c9feffdce2feff28e3feff6ce4feff7ce4feff88e4fefface4feff20ecfeff6cecfeffb0edfeffc0edfeffccedfefff0edfeff30fbffff
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name: