Skip to content

Commit 35760e2

Browse files
author
Justin Chung
committed
Split save paths for text and sqlite
1 parent 38497d6 commit 35760e2

6 files changed

Lines changed: 146 additions & 75 deletions

File tree

PSReadLine/Cmdlets.cs

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -239,14 +239,14 @@ public PSConsoleReadLineOptions(string hostName, bool usingLegacyConsole)
239239
var historyFileName = hostName + "_history.txt";
240240
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
241241
{
242-
HistorySavePath = System.IO.Path.Combine(
242+
HistorySavePathText = System.IO.Path.Combine(
243243
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
244244
"Microsoft",
245245
"Windows",
246246
"PowerShell",
247247
"PSReadLine",
248248
historyFileName);
249-
SqliteHistorySavePath = System.IO.Path.Combine(
249+
HistorySavePathSQLite = System.IO.Path.Combine(
250250
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
251251
"Microsoft",
252252
"Windows",
@@ -261,11 +261,16 @@ public PSConsoleReadLineOptions(string hostName, bool usingLegacyConsole)
261261

262262
if (!String.IsNullOrEmpty(historyPath))
263263
{
264-
HistorySavePath = System.IO.Path.Combine(
264+
HistorySavePathText = System.IO.Path.Combine(
265265
historyPath,
266266
"powershell",
267267
"PSReadLine",
268268
historyFileName);
269+
HistorySavePathSQLite = System.IO.Path.Combine(
270+
historyPath,
271+
"powershell",
272+
"PSReadLine",
273+
hostName + "_history.db");
269274
}
270275
else
271276
{
@@ -274,18 +279,26 @@ public PSConsoleReadLineOptions(string hostName, bool usingLegacyConsole)
274279

275280
if (!String.IsNullOrEmpty(home))
276281
{
277-
HistorySavePath = System.IO.Path.Combine(
282+
HistorySavePathText = System.IO.Path.Combine(
278283
home,
279284
".local",
280285
"share",
281286
"powershell",
282287
"PSReadLine",
283288
historyFileName);
289+
HistorySavePathSQLite = System.IO.Path.Combine(
290+
home,
291+
".local",
292+
"share",
293+
"powershell",
294+
"PSReadLine",
295+
hostName + "_history.db");
284296
}
285297
else
286298
{
287299
// No HOME, then don't save anything
288-
HistorySavePath = "/dev/null";
300+
HistorySavePathText = "/dev/null";
301+
HistorySavePathSQLite = "/dev/null";
289302
}
290303
}
291304
}
@@ -391,14 +404,23 @@ public object ContinuationPromptColor
391404
public ScriptBlock ViModeChangeHandler { get; set; }
392405

393406
/// <summary>
394-
/// The path to the saved history.
407+
/// The path to the text history file.
395408
/// </summary>
396-
public string HistorySavePath { get; set; }
409+
public string HistorySavePathText { get; set; }
397410

398411
/// <summary>
399412
/// The path to the SQLite history database.
400413
/// </summary>
401-
public string SqliteHistorySavePath { get; set; }
414+
public string HistorySavePathSQLite { get; set; }
415+
416+
/// <summary>
417+
/// Returns the active history save path based on the current <see cref="HistoryType"/>.
418+
/// </summary>
419+
public string HistorySavePath => HistoryType switch
420+
{
421+
HistoryType.SQLite => HistorySavePathSQLite,
422+
_ => HistorySavePathText,
423+
};
402424
public HistorySaveStyle HistorySaveStyle { get; set; }
403425

404426
/// <summary>
@@ -826,15 +848,27 @@ public HistorySaveStyle HistorySaveStyle
826848

827849
[Parameter]
828850
[ValidateNotNullOrEmpty]
829-
public string HistorySavePath
851+
public string HistorySavePathText
852+
{
853+
get => _historySavePathText;
854+
set
855+
{
856+
_historySavePathText = GetUnresolvedProviderPathFromPSPath(value);
857+
}
858+
}
859+
private string _historySavePathText;
860+
861+
[Parameter]
862+
[ValidateNotNullOrEmpty]
863+
public string HistorySavePathSQLite
830864
{
831-
get => _historySavePath;
865+
get => _historySavePathSQLite;
832866
set
833867
{
834-
_historySavePath = GetUnresolvedProviderPathFromPSPath(value);
868+
_historySavePathSQLite = GetUnresolvedProviderPathFromPSPath(value);
835869
}
836870
}
837-
private string _historySavePath;
871+
private string _historySavePathSQLite;
838872

839873
[Parameter]
840874
[ValidateRange(25, 1000)]

PSReadLine/History.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ private AddToHistoryOption GetAddToHistoryOption(string line, bool fromHistoryFi
209209
return AddToHistoryOption.MemoryAndFile;
210210
}
211211

212-
private void InitializeSQLiteDatabase()
212+
private void InitializeSQLiteDatabase(bool migrateTextHistory = false)
213213
{
214214
string baseConnectionString = $"Data Source={_options.HistorySavePath}";
215215
var connectionString = new SqliteConnectionStringBuilder(baseConnectionString)
@@ -288,8 +288,12 @@ FROM ExecutionHistory eh
288288
JOIN Locations l ON eh.LocationId = l.Id;";
289289
createTablesCommand.ExecuteNonQuery();
290290

291-
// Migrate existing text file history if it exists
292-
MigrateTextHistoryToSQLite(connection);
291+
// Only migrate text history on initial Text -> SQLite switch,
292+
// not when relocating an existing SQLite database.
293+
if (migrateTextHistory)
294+
{
295+
MigrateTextHistoryToSQLite(connection);
296+
}
293297
}
294298
}
295299
catch (SqliteException ex)
@@ -304,13 +308,9 @@ FROM ExecutionHistory eh
304308

305309
private void MigrateTextHistoryToSQLite(SqliteConnection connection)
306310
{
307-
// Derive the text history path from the SQLite path.
308-
// Both files share the same directory and host prefix:
309-
// ConsoleHost_history.txt (text)
310-
// ConsoleHost_history.db (SQLite)
311-
// By the time this runs, HistorySavePath is already the .db path.
312-
string textHistoryPath = Path.ChangeExtension(_options.HistorySavePath, ".txt");
313-
if (!File.Exists(textHistoryPath))
311+
// Use the dedicated text history path — no need to derive it from the SQLite path.
312+
string textHistoryPath = _options.HistorySavePathText;
313+
if (string.IsNullOrEmpty(textHistoryPath) || !File.Exists(textHistoryPath))
314314
{
315315
return; // No text history to migrate
316316
}

PSReadLine/Options.cs

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ private void SetOptionsInternal(SetPSReadLineOption options)
3131
Options.HistoryType = options.HistoryType;
3232
if (Options.HistoryType is HistoryType.SQLite)
3333
{
34-
Options.HistorySavePath = Options.SqliteHistorySavePath;
35-
// Check if the SQLite history file exists
34+
// HistorySavePath is now computed from HistoryType, so it already
35+
// points at HistorySavePathSQLite after the type switch above.
3636
if (!string.IsNullOrEmpty(Options.HistorySavePath) && !System.IO.File.Exists(Options.HistorySavePath))
3737
{
3838
_historyFileMutex?.Dispose();
3939
_historyFileMutex = new Mutex(false, GetHistorySaveFileMutexName());
40-
InitializeSQLiteDatabase();
40+
InitializeSQLiteDatabase(migrateTextHistory: true);
4141
_historyFileLastSavedSize = 0;
4242
}
43-
// For now remove all text history
43+
// Clear text history from memory and load SQLite history
4444
_singleton._history?.Clear();
4545
_singleton._currentHistoryIndex = 0;
4646

@@ -143,12 +143,38 @@ private void SetOptionsInternal(SetPSReadLineOption options)
143143
}
144144
Options.ViModeChangeHandler = options.ViModeChangeHandler;
145145
}
146-
if (options.HistorySavePath != null)
146+
if (options.HistorySavePathText != null)
147147
{
148-
Options.HistorySavePath = options.HistorySavePath;
149-
_historyFileMutex?.Dispose();
150-
_historyFileMutex = new Mutex(false, GetHistorySaveFileMutexName());
151-
_historyFileLastSavedSize = 0;
148+
Options.HistorySavePathText = options.HistorySavePathText;
149+
150+
// If currently in Text mode, reset the mutex for the new active path.
151+
if (Options.HistoryType is HistoryType.Text)
152+
{
153+
_historyFileMutex?.Dispose();
154+
_historyFileMutex = new Mutex(false, GetHistorySaveFileMutexName());
155+
_historyFileLastSavedSize = 0;
156+
}
157+
}
158+
if (options.HistorySavePathSQLite != null)
159+
{
160+
Options.HistorySavePathSQLite = options.HistorySavePathSQLite;
161+
162+
// If currently in SQLite mode, reconnect to the new database.
163+
if (Options.HistoryType is HistoryType.SQLite)
164+
{
165+
_historyFileMutex?.Dispose();
166+
_historyFileMutex = new Mutex(false, GetHistorySaveFileMutexName());
167+
_historyFileLastSavedSize = 0;
168+
169+
if (!System.IO.File.Exists(Options.HistorySavePath))
170+
{
171+
InitializeSQLiteDatabase();
172+
}
173+
174+
_singleton._history?.Clear();
175+
_singleton._currentHistoryIndex = 0;
176+
ReadSQLiteHistory(fromOtherSession: false);
177+
}
152178
}
153179
if (options._ansiEscapeTimeout.HasValue)
154180
{

PSReadLine/PSReadLine.format.ps1xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ $d = [Microsoft.PowerShell.KeyHandler]::GetGroupingDescription($_.Group)
100100
<PropertyName>HistoryNoDuplicates</PropertyName>
101101
</ListItem>
102102
<ListItem>
103-
<PropertyName>HistorySavePath</PropertyName>
103+
<PropertyName>HistorySavePathText</PropertyName>
104+
</ListItem>
105+
<ListItem>
106+
<PropertyName>HistorySavePathSQLite</PropertyName>
104107
</ListItem>
105108
<ListItem>
106109
<PropertyName>HistorySaveStyle</PropertyName>

test/HistoryTest.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public void ParallelHistorySaving()
4747
};
4848

4949
typeof(SetPSReadLineOption)
50-
.GetField("_historySavePath", BindingFlags.Instance | BindingFlags.NonPublic)
50+
.GetField("_historySavePathText", BindingFlags.Instance | BindingFlags.NonPublic)
5151
.SetValue(options, historySavingFile);
5252

5353
PSConsoleReadLine.SetOptions(options);
@@ -99,7 +99,7 @@ public void SensitiveHistoryDefaultBehavior_One()
9999
Test("", Keys(_.UpArrow, _.DownArrow));
100100

101101
var options = PSConsoleReadLine.GetOptions();
102-
var oldHistoryFilePath = options.HistorySavePath;
102+
var oldHistoryFilePath = options.HistorySavePathText;
103103
var oldHistorySaveStyle = options.HistorySaveStyle;
104104

105105
// AddToHistoryHandler should be set to the default handler.
@@ -136,7 +136,7 @@ public void SensitiveHistoryDefaultBehavior_One()
136136

137137
try
138138
{
139-
options.HistorySavePath = newHistoryFilePath;
139+
options.HistorySavePathText = newHistoryFilePath;
140140
options.HistorySaveStyle = newHistorySaveStyle;
141141
SetHistory(expectedHistoryItems);
142142

@@ -158,7 +158,7 @@ public void SensitiveHistoryDefaultBehavior_One()
158158
}
159159
finally
160160
{
161-
options.HistorySavePath = oldHistoryFilePath;
161+
options.HistorySavePathText = oldHistoryFilePath;
162162
options.HistorySaveStyle = oldHistorySaveStyle;
163163
File.Delete(newHistoryFilePath);
164164
}
@@ -173,7 +173,7 @@ public void SensitiveHistoryDefaultBehavior_Two()
173173
SetHistory();
174174

175175
var options = PSConsoleReadLine.GetOptions();
176-
var oldHistoryFilePath = options.HistorySavePath;
176+
var oldHistoryFilePath = options.HistorySavePathText;
177177
var oldHistorySaveStyle = options.HistorySaveStyle;
178178

179179
// AddToHistoryHandler should be set to the default handler.
@@ -253,7 +253,7 @@ public void SensitiveHistoryDefaultBehavior_Two()
253253

254254
try
255255
{
256-
options.HistorySavePath = newHistoryFilePath;
256+
options.HistorySavePathText = newHistoryFilePath;
257257
options.HistorySaveStyle = newHistorySaveStyle;
258258
SetHistory(expectedHistoryItems);
259259

@@ -275,7 +275,7 @@ public void SensitiveHistoryDefaultBehavior_Two()
275275
}
276276
finally
277277
{
278-
options.HistorySavePath = oldHistoryFilePath;
278+
options.HistorySavePathText = oldHistoryFilePath;
279279
options.HistorySaveStyle = oldHistorySaveStyle;
280280
File.Delete(newHistoryFilePath);
281281
}
@@ -291,7 +291,7 @@ public void SensitiveHistoryOptionalBehavior()
291291
Test("", Keys(_.UpArrow, _.DownArrow));
292292

293293
var options = PSConsoleReadLine.GetOptions();
294-
var oldHistoryFilePath = options.HistorySavePath;
294+
var oldHistoryFilePath = options.HistorySavePathText;
295295
var oldHistorySaveStyle = options.HistorySaveStyle;
296296

297297
// AddToHistoryHandler should be set to the default handler.
@@ -328,7 +328,7 @@ public void SensitiveHistoryOptionalBehavior()
328328

329329
try
330330
{
331-
options.HistorySavePath = newHistoryFilePath;
331+
options.HistorySavePathText = newHistoryFilePath;
332332
options.HistorySaveStyle = newHistorySaveStyle;
333333

334334
//
@@ -417,7 +417,7 @@ public void SensitiveHistoryOptionalBehavior()
417417
}
418418
finally
419419
{
420-
options.HistorySavePath = oldHistoryFilePath;
420+
options.HistorySavePathText = oldHistoryFilePath;
421421
options.HistorySaveStyle = oldHistorySaveStyle;
422422
options.AddToHistoryHandler = PSConsoleReadLineOptions.DefaultAddToHistoryHandler;
423423
File.Delete(newHistoryFilePath);
@@ -434,7 +434,7 @@ public void SensitiveHistoryOptionalBehaviorWithScriptBlock()
434434
Test("", Keys(_.UpArrow, _.DownArrow));
435435

436436
var options = PSConsoleReadLine.GetOptions();
437-
var oldHistoryFilePath = options.HistorySavePath;
437+
var oldHistoryFilePath = options.HistorySavePathText;
438438
var oldHistorySaveStyle = options.HistorySaveStyle;
439439

440440
// AddToHistoryHandler should be set to the default handler.
@@ -481,7 +481,7 @@ public void SensitiveHistoryOptionalBehaviorWithScriptBlock()
481481

482482
try
483483
{
484-
options.HistorySavePath = newHistoryFilePath;
484+
options.HistorySavePathText = newHistoryFilePath;
485485
options.HistorySaveStyle = newHistorySaveStyle;
486486

487487
//
@@ -570,7 +570,7 @@ public void SensitiveHistoryOptionalBehaviorWithScriptBlock()
570570
}
571571
finally
572572
{
573-
options.HistorySavePath = oldHistoryFilePath;
573+
options.HistorySavePathText = oldHistoryFilePath;
574574
options.HistorySaveStyle = oldHistorySaveStyle;
575575
options.AddToHistoryHandler = PSConsoleReadLineOptions.DefaultAddToHistoryHandler;
576576
File.Delete(newHistoryFilePath);

0 commit comments

Comments
 (0)