Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions ListingManager.Tests/ListingManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1440,4 +1440,72 @@ public void UpdateAllChapterListingNumbers_ListingsWithinListMissing_ListingsRen
Assert.Equivalent(expectedFiles, files);
}
#endregion UpdateAllChaptersListingNumbers

#region Constructor with useGit parameter
[Fact]
public void Constructor_WithUseGitTrue_InGitRepo_UsesGitStorageManager()
{
// Arrange
DirectoryInfo tempDir = CreateTempDirectory();
Repository.Init(tempDir.FullName);

// Act
ListingManager listingManager = new(tempDir, useGit: true);

// Assert
Assert.IsType<GitStorageManager>(listingManager.StorageManager);
}

[Fact]
public void Constructor_WithUseGitFalse_UsesOSStorageManager()
{
// Arrange
DirectoryInfo tempDir = CreateTempDirectory();

// Act
ListingManager listingManager = new(tempDir, useGit: false);

// Assert
Assert.IsType<OSStorageManager>(listingManager.StorageManager);
}

[Fact]
public void Constructor_WithUseGitTrue_NotInGitRepo_ThrowsInvalidOperationException()
{
// Arrange
DirectoryInfo tempDir = CreateTempDirectory();

// Act & Assert
var exception = Assert.Throws<InvalidOperationException>(() => new ListingManager(tempDir, useGit: true));
Assert.Contains("--git option was specified", exception.Message);
Assert.Contains("not in a git repository", exception.Message);
}

[Fact]
public void Constructor_Default_InGitRepo_UsesGitStorageManager()
{
// Arrange
DirectoryInfo tempDir = CreateTempDirectory();
Repository.Init(tempDir.FullName);

// Act
ListingManager listingManager = new(tempDir);

// Assert
Assert.IsType<GitStorageManager>(listingManager.StorageManager);
}

[Fact]
public void Constructor_Default_NotInGitRepo_UsesOSStorageManager()
{
// Arrange
DirectoryInfo tempDir = CreateTempDirectory();

// Act
ListingManager listingManager = new(tempDir);

// Assert
Assert.IsType<OSStorageManager>(listingManager.StorageManager);
}
#endregion Constructor with useGit parameter
}
20 changes: 19 additions & 1 deletion ListingManager/ListingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,25 @@ public partial class ListingManager

public ListingManager(DirectoryInfo pathToChapter)
{
StorageManager = Repository.IsValid(pathToChapter.FullName) ? new GitStorageManager(pathToChapter.FullName) : new OSStorageManager();
string? repoPath = Repository.Discover(pathToChapter.FullName);
StorageManager = repoPath is not null ? new GitStorageManager(repoPath) : new OSStorageManager();
}

public ListingManager(DirectoryInfo pathToChapter, bool useGit)
{
if (useGit)
{
string? repoPath = Repository.Discover(pathToChapter.FullName);
if (repoPath is null)
{
throw new InvalidOperationException($"The --git option was specified, but the directory '{pathToChapter.FullName}' is not in a git repository.");
}
StorageManager = new GitStorageManager(repoPath);
}
else
{
StorageManager = new OSStorageManager();
}
}

public ListingManager(DirectoryInfo pathToChapter, IStorageManager storageManager)
Expand Down
11 changes: 10 additions & 1 deletion ListingManager/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ public static RootCommand GetRootCommand()
Description = "All listings are in a single directory and not separated into chapter and chapter test directories.",
};

Option<bool> gitOption = new("--git")
{
Description = "Use git mv for moving files instead of OS file operations. Requires the directory to be a valid git repository.",
};

Command listingUpdating = new("update", "Updates namespaces and filenames for all listings and accompanying tests within a chapter");
listingUpdating.Arguments.Add(directoryInArgument);
listingUpdating.Options.Add(verboseOption);
listingUpdating.Options.Add(previewOption);
listingUpdating.Options.Add(byFolderOption);
listingUpdating.Options.Add(singleDirOption);
listingUpdating.Options.Add(allChaptersOption);
listingUpdating.Options.Add(gitOption);

listingUpdating.SetAction((ParseResult parseResult) =>
{
Expand All @@ -63,9 +69,12 @@ public static RootCommand GetRootCommand()
bool byFolder = parseResult.GetValue(byFolderOption);
bool singleDir = parseResult.GetValue(singleDirOption);
bool allChapters = parseResult.GetValue(allChaptersOption);
bool useGit = parseResult.GetValue(gitOption);

Console.WriteLine($"Updating listings within: {directoryIn}");
ListingManager listingManager = new(directoryIn);
// When --git is specified, use the explicit constructor to force GitStorageManager.
// When --git is NOT specified, use the parameterless constructor for auto-detection.
ListingManager listingManager = useGit ? new(directoryIn, useGit) : new(directoryIn);
if (allChapters)
{
listingManager.UpdateAllChapterListingNumbers(directoryIn, verbose, preview, byFolder, singleDir);
Expand Down
69 changes: 51 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,37 +11,70 @@ Run `dotnet tool update -g IntelliTect.EssentialCSharp.ListingManager`. This wil

# Usage

Any command can be run with these optional parameters.
Run `ListingManager` from the command line.

- `verbose` -> provides more detail into what the command is doing
For available commands run `ListingManager -h`. This will display all the commands available to you.

`ListingUpdating` can be run with the following additional optional parameters.
## Update Command

- `preview` -> leave files in place but still print actions that would take place to console
- `by-folder` -> changes a listing's chapter based on the chapter number in the chapter's path
- `chapter-only` -> changes only the chapter of the listing, leaving the listing number unchanged. Use with `byfolder`
The `update` command updates namespaces and filenames for all listings and accompanying tests within a chapter.

Run `ListingManager` from the command line.
### Basic Usage

For available commands run `ListingManager -h`. This will display all the commands available to you.
```bash
ListingManager update <directoryIn>
```

### Optional Parameters

- `--verbose` -> Displays more detailed messages in the log
- `--preview` -> Displays the changes that will be made without actually making them
- `--by-folder` -> Updates namespaces and filenames for all listings and accompanying tests within a folder
- `--single-dir` -> All listings are in a single directory and not separated into chapter and chapter test directories
- `--all-chapters` -> The passed in path is the parent directory to many chapter directories rather than a single chapter directory
- `--git` -> Use git mv for moving files instead of OS file operations. Requires the directory to be in a git repository. This preserves git history for renamed files.

### Examples

```bash
# Update listings in a chapter with preview
ListingManager update "user/EssentialCSharp/src/Chapter03/" --preview --verbose

To update Listings at a path provide the Chapter's path and specify the `ListingUpdating` mode.
`ListingManager --path "user/EssentialCSharp/src/Chapter03/" --mode ListingUpdating` or
`ListingManager --path "user/EssentialCSharp/src/Chapter03/"`
NOTE: It is highly recommended that you commit and push your changes before running this command. Additionally you should
run this command with `--preview` and `--verbose` specified to ensure there are no adverse affects. Once you are confident
# Update listings using git mv (preserves git history)
ListingManager update "user/EssentialCSharp/src/Chapter03/" --git --preview --verbose

# Update all chapters
ListingManager update "user/EssentialCSharp/src/" --all-chapters --preview --verbose
```

**NOTE:** It is highly recommended that you commit and push your changes before running this command. Additionally you should
run this command with `--preview` and `--verbose` specified to ensure there are no adverse effects. Once you are confident
that the proposed changes are what you want, you can run the command without the `--preview` modifier.

To find potentially mismatched listings in a chapter run,
`ListingManager --path "user/EssentialCSharp/src/Chapter03/" --mode ScanForMismatchedListings`. Potentially mismatched listings
will be printed to the console.
## Scan Commands

To run all chapters in powershell from ListingManager directory,
### Scan for Mismatched Listings

To find potentially mismatched listings in a chapter run:
```bash
ListingManager scan listings <directoryIn>
```

### Scan for Missing Tests

To find missing tests:
```bash
ListingManager scan tests <directoryIn>
```

### Running All Chapters in PowerShell

From the ListingManager directory:
```powershell
Get-ChildItem -Path 'insert.srcPathNameHere' -Directory | Where-Object {
!$_.name.EndsWith("Tests")
} | ForEach-Object {
listingmanager --path $_.FullName --preview --verbose
listingmanager update $_.FullName --preview --verbose
}
```

Expand Down
Loading