forked from github/copilot-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSessionFsProvider.cs
More file actions
216 lines (192 loc) · 9.56 KB
/
Copy pathSessionFsProvider.cs
File metadata and controls
216 lines (192 loc) · 9.56 KB
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
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------------------------------------------*/
using GitHub.Copilot.SDK.Rpc;
namespace GitHub.Copilot.SDK;
/// <summary>
/// Base class for session filesystem providers. Subclasses override the
/// virtual methods and use normal C# patterns (return values, throw exceptions).
/// The base class catches exceptions and converts them to <see cref="SessionFsError"/>
/// results expected by the runtime.
/// </summary>
public abstract class SessionFsProvider : ISessionFsHandler
{
/// <summary>Reads the full content of a file. Throw if the file does not exist.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>The file content as a UTF-8 string.</returns>
protected abstract Task<string> ReadFileAsync(string path, CancellationToken cancellationToken);
/// <summary>Writes content to a file, creating it (and parent directories) if needed.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="content">Content to write.</param>
/// <param name="mode">Optional POSIX-style permission mode. Null means use OS default.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task WriteFileAsync(string path, string content, int? mode, CancellationToken cancellationToken);
/// <summary>Appends content to a file, creating it (and parent directories) if needed.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="content">Content to append.</param>
/// <param name="mode">Optional POSIX-style permission mode. Null means use OS default.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task AppendFileAsync(string path, string content, int? mode, CancellationToken cancellationToken);
/// <summary>Checks whether a path exists.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns><c>true</c> if the path exists, <c>false</c> otherwise.</returns>
protected abstract Task<bool> ExistsAsync(string path, CancellationToken cancellationToken);
/// <summary>Gets metadata about a file or directory. Throw if the path does not exist.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task<SessionFsStatResult> StatAsync(string path, CancellationToken cancellationToken);
/// <summary>Creates a directory (and optionally parents). Does not fail if it already exists.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="recursive">Whether to create parent directories.</param>
/// <param name="mode">Optional POSIX-style permission mode (e.g., 0x1FF for 0777). Null means use OS default.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task MkdirAsync(string path, bool recursive, int? mode, CancellationToken cancellationToken);
/// <summary>Lists entry names in a directory. Throw if the directory does not exist.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task<IList<string>> ReaddirAsync(string path, CancellationToken cancellationToken);
/// <summary>Lists entries with type info in a directory. Throw if the directory does not exist.</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task<IList<SessionFsReaddirWithTypesEntry>> ReaddirWithTypesAsync(string path, CancellationToken cancellationToken);
/// <summary>Removes a file or directory. Throw if the path does not exist (unless <paramref name="force"/> is true).</summary>
/// <param name="path">SessionFs-relative path.</param>
/// <param name="recursive">Whether to remove directory contents recursively.</param>
/// <param name="force">If true, do not throw when the path does not exist.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task RmAsync(string path, bool recursive, bool force, CancellationToken cancellationToken);
/// <summary>Renames/moves a file or directory.</summary>
/// <param name="src">Source path.</param>
/// <param name="dest">Destination path.</param>
/// <param name="cancellationToken">Cancellation token.</param>
protected abstract Task RenameAsync(string src, string dest, CancellationToken cancellationToken);
// ---- ISessionFsHandler implementation (private, handles error mapping) ----
async Task<SessionFsReadFileResult> ISessionFsHandler.ReadFileAsync(SessionFsReadFileRequest request, CancellationToken cancellationToken)
{
try
{
var content = await ReadFileAsync(request.Path, cancellationToken).ConfigureAwait(false);
return new SessionFsReadFileResult { Content = content };
}
catch (Exception ex)
{
return new SessionFsReadFileResult { Error = ToSessionFsError(ex) };
}
}
async Task<SessionFsError?> ISessionFsHandler.WriteFileAsync(SessionFsWriteFileRequest request, CancellationToken cancellationToken)
{
try
{
await WriteFileAsync(request.Path, request.Content, (int?)request.Mode, cancellationToken).ConfigureAwait(false);
return null;
}
catch (Exception ex)
{
return ToSessionFsError(ex);
}
}
async Task<SessionFsError?> ISessionFsHandler.AppendFileAsync(SessionFsAppendFileRequest request, CancellationToken cancellationToken)
{
try
{
await AppendFileAsync(request.Path, request.Content, (int?)request.Mode, cancellationToken).ConfigureAwait(false);
return null;
}
catch (Exception ex)
{
return ToSessionFsError(ex);
}
}
async Task<SessionFsExistsResult> ISessionFsHandler.ExistsAsync(SessionFsExistsRequest request, CancellationToken cancellationToken)
{
try
{
var exists = await ExistsAsync(request.Path, cancellationToken).ConfigureAwait(false);
return new SessionFsExistsResult { Exists = exists };
}
catch
{
return new SessionFsExistsResult { Exists = false };
}
}
async Task<SessionFsStatResult> ISessionFsHandler.StatAsync(SessionFsStatRequest request, CancellationToken cancellationToken)
{
try
{
return await StatAsync(request.Path, cancellationToken).ConfigureAwait(false);
}
catch (Exception ex)
{
return new SessionFsStatResult { Error = ToSessionFsError(ex) };
}
}
async Task<SessionFsError?> ISessionFsHandler.MkdirAsync(SessionFsMkdirRequest request, CancellationToken cancellationToken)
{
try
{
await MkdirAsync(request.Path, request.Recursive ?? false, (int?)request.Mode, cancellationToken).ConfigureAwait(false);
return null;
}
catch (Exception ex)
{
return ToSessionFsError(ex);
}
}
async Task<SessionFsReaddirResult> ISessionFsHandler.ReaddirAsync(SessionFsReaddirRequest request, CancellationToken cancellationToken)
{
try
{
var entries = await ReaddirAsync(request.Path, cancellationToken).ConfigureAwait(false);
return new SessionFsReaddirResult { Entries = entries };
}
catch (Exception ex)
{
return new SessionFsReaddirResult { Error = ToSessionFsError(ex) };
}
}
async Task<SessionFsReaddirWithTypesResult> ISessionFsHandler.ReaddirWithTypesAsync(SessionFsReaddirWithTypesRequest request, CancellationToken cancellationToken)
{
try
{
var entries = await ReaddirWithTypesAsync(request.Path, cancellationToken).ConfigureAwait(false);
return new SessionFsReaddirWithTypesResult { Entries = entries };
}
catch (Exception ex)
{
return new SessionFsReaddirWithTypesResult { Error = ToSessionFsError(ex) };
}
}
async Task<SessionFsError?> ISessionFsHandler.RmAsync(SessionFsRmRequest request, CancellationToken cancellationToken)
{
try
{
await RmAsync(request.Path, request.Recursive ?? false, request.Force ?? false, cancellationToken).ConfigureAwait(false);
return null;
}
catch (Exception ex)
{
return ToSessionFsError(ex);
}
}
async Task<SessionFsError?> ISessionFsHandler.RenameAsync(SessionFsRenameRequest request, CancellationToken cancellationToken)
{
try
{
await RenameAsync(request.Src, request.Dest, cancellationToken).ConfigureAwait(false);
return null;
}
catch (Exception ex)
{
return ToSessionFsError(ex);
}
}
private static SessionFsError ToSessionFsError(Exception ex)
{
var code = ex is FileNotFoundException or DirectoryNotFoundException
? SessionFsErrorCode.ENOENT
: SessionFsErrorCode.UNKNOWN;
return new SessionFsError { Code = code, Message = ex.Message };
}
}