diff --git a/.editorconfig b/.editorconfig index 8b0b175..d793869 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,7 +10,7 @@ indent_style = space tab_width = 4 # Naming Conventions -dotnet_naming_style.pascal_case_style.capitalization = pascal_case +dotnet_naming_style.camel_case.capitalization = camel_case # New line preferences csharp_new_line_before_open_brace = none diff --git a/justfile b/justfile index d9be799..8ad837f 100644 --- a/justfile +++ b/justfile @@ -1,2 +1,31 @@ -publish: - @dotnet publish --configuration Release chksum.csproj +default: + @just --list + +project_name := `printf '%s\n' "${PWD##*/}"` +uppercase_project_name := capitalize(project_name) + +setup: + @mkdir src + @dotnet new sln --name src/{{project_name}} + @dotnet new classlib -o src/{{uppercase_project_name}} + @dotnet new xunit -o src/{{uppercase_project_name}}.Tests + @dotnet sln add src/{{uppercase_project_name}}/{{uppercase_project_name}}.csproj + @dotnet sln add src/{{uppercase_project_name}}.Tests/{{uppercase_project_name}}.Tests.csproj + @dotnet add src/{{uppercase_project_name}}/{{uppercase_project_name}}.csproj reference src/{{uppercase_project_name}}.Tests/{{uppercase_project_name}}.Tests.csproj + +run: + @dotnet run + +build: + @dotnet build src/{{uppercase_project_name}}/{{uppercase_project_name}}.csproj + @dotnet build src/{{uppercase_project_name}}.Tests/{{uppercase_project_name}}.Tests.csproj + +publish: format + @dotnet publish --configuration Release src/{{uppercase_project_name}}/{{uppercase_project_name}}.csproj + +format: + @dotnet format src/{{uppercase_project_name}} + @dotnet format src/{{uppercase_project_name}}.Tests + +test: build + @dotnet test src/{{uppercase_project_name}}.Tests diff --git a/src/Chksum.Tests/Chksum.Tests.csproj b/src/Chksum.Tests/Chksum.Tests.csproj new file mode 100644 index 0000000..10cd649 --- /dev/null +++ b/src/Chksum.Tests/Chksum.Tests.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/src/Chksum.Tests/Usings.cs b/src/Chksum.Tests/Usings.cs new file mode 100644 index 0000000..7fef4b0 --- /dev/null +++ b/src/Chksum.Tests/Usings.cs @@ -0,0 +1,2 @@ +global using Xunit; +global using FluentAssertions; \ No newline at end of file diff --git a/src/Chksum.Tests/doTheThingTest.cs b/src/Chksum.Tests/doTheThingTest.cs new file mode 100644 index 0000000..94ae38e --- /dev/null +++ b/src/Chksum.Tests/doTheThingTest.cs @@ -0,0 +1,8 @@ +namespace Chksum.Tests; + +public class doTheThingTest { + [Fact] + public void doTheThing_willNotThrowAnException() { + + } +} \ No newline at end of file diff --git a/chksum.csproj b/src/Chksum/Chksum.csproj similarity index 83% rename from chksum.csproj rename to src/Chksum/Chksum.csproj index 8090b43..6db87ee 100644 --- a/chksum.csproj +++ b/src/Chksum/Chksum.csproj @@ -1,5 +1,9 @@ + + + + Exe net7.0 diff --git a/Program.cs b/src/Chksum/Program.cs similarity index 88% rename from Program.cs rename to src/Chksum/Program.cs index 4f3ba64..15e4b64 100644 --- a/Program.cs +++ b/src/Chksum/Program.cs @@ -1,3 +1,6 @@ +using System; +using Chksum.Utils; + public class Program { static void Main(string[] args) { @@ -11,7 +14,9 @@ public class Program { return; } - Chksum.getBaseDir(); + ChksumUtils utils = new ChksumUtils(); + + utils.getBaseDir(); Console.ForegroundColor = ConsoleColor.Green; switch (args[0]) { @@ -19,7 +24,7 @@ public class Program { Console.WriteLine("Starting the checksum process."); Console.ResetColor(); - Chksum.doTheThing(); + utils.doTheThing(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Checksum process finished"); @@ -28,7 +33,7 @@ public class Program { Console.WriteLine("Counting md5 checksum files."); Console.ResetColor(); - Chksum.countAllMd5Checksums(); + utils.countAllMd5Checksums(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Finished counting all md5 checksum files."); @@ -37,7 +42,7 @@ public class Program { Console.WriteLine("Deleting all md5 checksum files."); Console.ResetColor(); - Chksum.deleteAllMd5Checksums(); + utils.deleteAllMd5Checksums(); Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Deleted all md5 checksum files."); @@ -46,10 +51,10 @@ public class Program { Console.WriteLine("Comparing all md5 checksum files. If there is none, creating one."); Console.ResetColor(); - Chksum.compareChecksums(); + utils.compareChecksums(); break; case "createDB": - Chksum.initializeDB(); + utils.initializeDB(); break; case "help": PrintAvailableOptions(); diff --git a/chksum.cs b/src/Chksum/chksum.cs similarity index 58% rename from chksum.cs rename to src/Chksum/chksum.cs index 7cb4265..4aa4d03 100644 --- a/chksum.cs +++ b/src/Chksum/chksum.cs @@ -1,3 +1,5 @@ +using System; +using System.IO; using Microsoft.Data.Sqlite; // Go into folder @@ -5,14 +7,15 @@ using Microsoft.Data.Sqlite; // If there is a file. Calculate md5sum > filename.md5 // If there is no file. Repeat -public class Chksum { - +namespace Chksum.Utils; +public class ChksumUtils { + // int getDirectoryCount() { // int folderCount = Directory.GetDirectories(Directory.GetCurrentDirectory()).Length; // Get folder count in current directory // return folderCount; // } - private static int getFileCount() { + private int getFileCount() { int fileCount = Directory.GetFiles(Directory.GetCurrentDirectory()).Length; // Get file count in current directory return fileCount; } @@ -22,31 +25,44 @@ public class Chksum { // return parentFolder; // } - public static string DatabaseRoot { get; set; } - public static void getBaseDir() { + public string DatabaseRoot { get; set; } + public void getBaseDir() { DatabaseRoot = AppDomain.CurrentDomain.BaseDirectory; } - - public static void initializeDB() { - using (var connection = new SqliteConnection("Data Source=chksum.db")) { - connection.Open(); + public void initializeDB() { + if (!File.Exists("chksum.db")) { + using (var connection = new SqliteConnection("Data Source=chksum.db")) { + connection.Open(); + + var command = connection.CreateCommand(); + command.CommandText = + @" + CREATE TABLE file ( + filehash TEXT NOT NULL PRIMARY KEY, + filename TEXT NOT NULL, + pathtofile TEXT NOT NULL, + artist TEXT, + playbacklength INTEGER + ); + "; + command.ExecuteNonQuery(); + } + } + } + + public void cleanDB() { + using (var connection = new SqliteConnection("Data Source=" + DatabaseRoot + "chksum.db")) { var command = connection.CreateCommand(); command.CommandText = @" - CREATE TABLE file ( - filehash TEXT NOT NULL PRIMARY KEY, - filename TEXT NOT NULL, - pathtofile TEXT NOT NULL, - artist TEXT, - playbacklength INTEGER - ); + vacuum; "; command.ExecuteNonQuery(); } } - private static string CalculateMD5(string filename) { + private string CalculateMD5(string filename) { using (var md5 = System.Security.Cryptography.MD5.Create()) { using (var stream = File.OpenRead(filename)) { var hash = md5.ComputeHash(stream); @@ -55,49 +71,79 @@ public class Chksum { } } - public static void doTheThing() { - foreach (var directory in Directory.GetDirectories(Directory.GetCurrentDirectory())) { - Directory.SetCurrentDirectory(directory); // Set new root - if (getFileCount() >= 1) { - DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory()); - FileInfo[] files = dir.GetFiles(); - foreach (FileInfo file in files) { - string fileName = file.Name; - string absolutePathToFile = Path.GetFullPath(fileName); - string pathToFile = Path.GetRelativePath(DatabaseRoot, absolutePathToFile); - string fileHash = CalculateMD5(fileName); + public void doTheThing() { + foreach (var directory in Directory.GetDirectories(Directory.GetCurrentDirectory())) using (var connection = new SqliteConnection("Data Source=" + DatabaseRoot + "chksum.db;Mode=ReadWrite")) { + Directory.SetCurrentDirectory(directory); // Set new root + if (getFileCount() >= 1) { + DirectoryInfo dir = new DirectoryInfo(Directory.GetCurrentDirectory()); + FileInfo[] files = dir.GetFiles(); + foreach (FileInfo file in files) { + string fileName = file.Name; + string absolutePathToFile = Path.GetFullPath(fileName); + string pathToFile = Path.GetRelativePath(DatabaseRoot, absolutePathToFile); + string fileHash = CalculateMD5(fileName); - using (var connection = new SqliteConnection("Data Source=" + DatabaseRoot + "chksum.db;Mode=ReadWrite")) { - connection.Open(); + if (checkIfFileAlreadyExists(fileHash, fileName) == false) { + connection.Open(); - var command = connection.CreateCommand(); - command.CommandText = - @" + var command = connection.CreateCommand(); + command.CommandText = + @" INSERT INTO file (filehash, filename, pathtofile) VALUES ($filehash, $filename, $pathtofile) - "; - command.Parameters.AddWithValue("$filehash", fileHash); - command.Parameters.AddWithValue("$filename", fileName); - command.Parameters.AddWithValue("$pathtofile", pathToFile); - command.ExecuteNonQuery(); + "; + command.Parameters.AddWithValue("$filehash", fileHash); + command.Parameters.AddWithValue("$filename", fileName); + command.Parameters.AddWithValue("$pathtofile", pathToFile); + command.ExecuteNonQuery(); + } } } + doTheThing(); } - doTheThing(); + } + + private bool checkIfFileAlreadyExists(string fileHash, string fileName) { + string filehash = string.Empty; + string filename = string.Empty; + + using (var connection = new SqliteConnection("Data Source=" + DatabaseRoot + "chksum.db;Mode=ReadWrite")) { + connection.Open(); + + var command = connection.CreateCommand(); + command.CommandText = + @" + SELECT filehash, filename FROM file WHERE filehash = $filehash + "; + command.Parameters.AddWithValue("$filehash", fileHash); + + using (var reader = command.ExecuteReader()) { + while (reader.Read()) { + filehash = reader.GetString(0); + filename = reader.GetString(1); + } + } + } + + if (fileHash == filehash) { + Console.WriteLine($"Duplicate files found: {fileName} with the hash {fileHash} is identical to {filename} with the hash {filehash}"); + return true; + } else { + return false; } } - private static int getTotalFileCount() { + private int getTotalFileCount() { int totalFileCount = Directory.GetFiles(Directory.GetCurrentDirectory(), "*", SearchOption.AllDirectories).Length; return totalFileCount - 1; // Remove the program from the totalFileCount } - public static void countAllMd5Checksums() { + public void countAllMd5Checksums() { int totalMD5FileCount = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.md5", SearchOption.AllDirectories).Length; Console.WriteLine("There are " + totalMD5FileCount + " md5 checksums"); } - public static void deleteAllMd5Checksums() { + public void deleteAllMd5Checksums() { foreach (var directory in Directory.GetDirectories(Directory.GetCurrentDirectory())) { Directory.SetCurrentDirectory(directory); // Set new root if (getFileCount() >= 1) { @@ -115,7 +161,7 @@ public class Chksum { } } - public static void compareChecksums() { + public void compareChecksums() { foreach (var directory in Directory.GetDirectories(Directory.GetCurrentDirectory())) { Directory.SetCurrentDirectory(directory); // Set new root if (getFileCount() >= 1) { diff --git a/debugchksum.cs b/src/Chksum/debugchksum.cs similarity index 100% rename from debugchksum.cs rename to src/Chksum/debugchksum.cs diff --git a/src/chksum.sln b/src/chksum.sln new file mode 100644 index 0000000..b5f119a --- /dev/null +++ b/src/chksum.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chksum", "Chksum\Chksum.csproj", "{BBC56294-03CF-42E0-A838-75AF41EEE32B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Chksum.Tests", "Chksum.Tests\Chksum.Tests.csproj", "{239727BC-7124-4985-A6F3-2700295AA06F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BBC56294-03CF-42E0-A838-75AF41EEE32B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BBC56294-03CF-42E0-A838-75AF41EEE32B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BBC56294-03CF-42E0-A838-75AF41EEE32B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BBC56294-03CF-42E0-A838-75AF41EEE32B}.Release|Any CPU.Build.0 = Release|Any CPU + {239727BC-7124-4985-A6F3-2700295AA06F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {239727BC-7124-4985-A6F3-2700295AA06F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {239727BC-7124-4985-A6F3-2700295AA06F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {239727BC-7124-4985-A6F3-2700295AA06F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal