brch 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3135,7 +3135,7 @@ var shouldIgnore = (absPath, repoRoot, ignorePatterns) => {
3135
3135
  if (relPath === "") {
3136
3136
  return false;
3137
3137
  }
3138
- if (relPath === VCS_DIR || relPath.startsWith(`${VCS_DIR}/`)) {
3138
+ if (relPath === VCS_DIR || relPath.startsWith(`${VCS_DIR}/`) || relPath === `./${VCS_DIR}` || relPath.startsWith(`./${VCS_DIR}/`)) {
3139
3139
  return true;
3140
3140
  }
3141
3141
  return matchesIgnorePattern(absPath, repoRoot, ignorePatterns);
@@ -3196,10 +3196,12 @@ commit will be skipped. Only files that exist and have been modified will be sta
3196
3196
  console.log(source_default.green("Staged:"));
3197
3197
  staged.forEach((path) => console.log(source_default.green(" - ") + path));
3198
3198
  }
3199
+ console.log();
3199
3200
  if (skipped.length > 0) {
3200
3201
  console.log(source_default.yellow("Skipped (unchanged or not found):"));
3201
3202
  skipped.forEach((path) => console.log(source_default.yellow(" - ") + path));
3202
3203
  }
3204
+ console.log();
3203
3205
  if (staged.length === 0 && skipped.length === 0) {
3204
3206
  console.log(source_default.yellow("Nothing to add."));
3205
3207
  }
@@ -3282,7 +3284,6 @@ var commitChanges = async (message) => {
3282
3284
  const branchRefPath = path2.join(repoRoot, REFS_HEAD_PATH, branchName);
3283
3285
  await mkdir4(path2.dirname(branchRefPath), { recursive: true });
3284
3286
  await writeFile4(branchRefPath, commitHash);
3285
- await writeFile4(INDEX_PATH, JSON.stringify([]));
3286
3287
  console.log(`Commit successfully created: ${commitHash}`);
3287
3288
  } catch (error) {
3288
3289
  const message2 = error instanceof Error ? error.message : String(error);
@@ -4826,7 +4827,15 @@ var log = async (options) => {
4826
4827
  };
4827
4828
 
4828
4829
  // src/commands/logCommand.ts
4829
- var logCommand = new Command("log").description("Show commit history for the current repository in reverse chronological order").option("-L, --limit <number>", "Limit the number of commits to display").addHelpText("after", "Displays each commit with author, date, and message. Use -L or --limit to restrict output to a specific number of commits.").action(log);
4830
+ var logCommand = new Command("log").description("Show commit history for the current repository in reverse chronological order").option("-L, --limit <number>", "Limit the number of commits to display").addHelpText("after", `
4831
+ Examples:
4832
+ $ brch log Show all commits
4833
+ $ brch log -L 5 Show the last 5 commits
4834
+ $ brch log --limit 10 Show the last 10 commits
4835
+
4836
+ Displays each commit with author, date, hash, and message.
4837
+ Commits are shown from newest to oldest.
4838
+ `).action(log);
4830
4839
 
4831
4840
  // src/services/statusService.ts
4832
4841
  import fs4 from "fs/promises";
@@ -4862,11 +4871,9 @@ var getTrackedFiles = async (commitHash) => {
4862
4871
  try {
4863
4872
  const commitPath = path4.join(OBJECTS_PATH, commitHash.substring(0, 2), commitHash.substring(2));
4864
4873
  const commitData = JSON.parse(await fs4.readFile(commitPath, "utf-8"));
4865
- if (commitData.tree) {
4866
- const treePath = path4.join(OBJECTS_PATH, commitData.tree.substring(0, 2), commitData.tree.substring(2));
4867
- const treeData = JSON.parse(await fs4.readFile(treePath, "utf-8"));
4868
- for (const [file, hash] of Object.entries(treeData)) {
4869
- trackedFiles.set(file, hash);
4874
+ if (commitData.files && Array.isArray(commitData.files)) {
4875
+ for (const entry of commitData.files) {
4876
+ trackedFiles.set(entry.path, entry.hash);
4870
4877
  }
4871
4878
  }
4872
4879
  } catch (error) {}
@@ -4887,7 +4894,28 @@ var readIndex3 = async () => {
4887
4894
  return [];
4888
4895
  }
4889
4896
  };
4890
- var stripLeadingDot = (p) => p.startsWith("./") ? p.slice(2) : p;
4897
+ var normalizeRelativePath3 = (pathValue) => {
4898
+ const normalized = pathValue.split("\\").join("/");
4899
+ if (normalized && !normalized.startsWith("./") && !normalized.startsWith("../") && !normalized.startsWith("/")) {
4900
+ return "./" + normalized;
4901
+ }
4902
+ return normalized;
4903
+ };
4904
+ var walk = async (dir, repoRoot, ignorePatterns) => {
4905
+ let files = [];
4906
+ const entries = await fs4.readdir(dir, { withFileTypes: true });
4907
+ for (const entry of entries) {
4908
+ const res = path4.resolve(dir, entry.name);
4909
+ if (entry.name === VCS_DIR || shouldIgnore2(entry.name, ignorePatterns))
4910
+ continue;
4911
+ if (entry.isDirectory()) {
4912
+ files = files.concat(await walk(res, repoRoot, ignorePatterns));
4913
+ } else {
4914
+ files.push(normalizeRelativePath3(path4.relative(repoRoot, res)));
4915
+ }
4916
+ }
4917
+ return files;
4918
+ };
4891
4919
  var status = async () => {
4892
4920
  try {
4893
4921
  const currentBranch = await getCurrentBranchName();
@@ -4895,65 +4923,88 @@ var status = async () => {
4895
4923
  const trackedFiles = await getTrackedFiles(currentHead);
4896
4924
  const ignorePatterns = await getIgnorePatterns();
4897
4925
  const indexEntries = await readIndex3();
4898
- const stagedSet = new Set(indexEntries.map((e) => stripLeadingDot(e.path)));
4926
+ const indexMap = new Map;
4927
+ for (const entry of indexEntries) {
4928
+ indexMap.set(entry.path, entry.hash);
4929
+ }
4899
4930
  console.log(`On branch ${source_default.cyan(currentBranch || "detached HEAD")}`);
4900
- const workdir = process.cwd();
4901
- const entries = await fs4.readdir(workdir, { withFileTypes: true });
4902
- const stagedFiles = [];
4931
+ const repoRoot = process.cwd();
4932
+ const allFiles = await walk(repoRoot, repoRoot, ignorePatterns);
4933
+ const stagedAdditions = [];
4934
+ const stagedModifications = [];
4935
+ const stagedDeletions = [];
4903
4936
  const modifiedFiles = [];
4904
- const untrackedItems = [];
4905
- for (const entry of entries) {
4906
- if (entry.name === VCS_DIR) {
4907
- continue;
4908
- }
4909
- if (shouldIgnore2(entry.name, ignorePatterns)) {
4910
- continue;
4911
- }
4912
- if (entry.isFile()) {
4913
- if (stagedSet.has(entry.name)) {
4914
- stagedFiles.push(entry.name);
4915
- continue;
4937
+ const deletedFiles = [];
4938
+ const untrackedFiles = [];
4939
+ const allKnownPaths = new Set([
4940
+ ...allFiles,
4941
+ ...indexMap.keys(),
4942
+ ...trackedFiles.keys()
4943
+ ]);
4944
+ const worktreeSet = new Set(allFiles);
4945
+ for (const relPath of allKnownPaths) {
4946
+ const indexHash = indexMap.get(relPath);
4947
+ const headHash = trackedFiles.get(relPath);
4948
+ const isWorktree = worktreeSet.has(relPath);
4949
+ if (indexHash !== headHash) {
4950
+ if (!headHash && indexHash) {
4951
+ stagedAdditions.push(relPath);
4952
+ } else if (headHash && !indexHash) {
4953
+ stagedDeletions.push(relPath);
4954
+ } else if (headHash && indexHash && headHash !== indexHash) {
4955
+ stagedModifications.push(relPath);
4916
4956
  }
4917
- const filePath = path4.join(workdir, entry.name);
4918
- const fileHash = hashContent(filePath);
4919
- const trackedHash = trackedFiles.get(entry.name);
4920
- if (trackedHash) {
4921
- if (fileHash !== trackedHash) {
4922
- modifiedFiles.push(entry.name);
4957
+ }
4958
+ if (isWorktree) {
4959
+ const fileBuffer = await fs4.readFile(path4.join(repoRoot, relPath));
4960
+ const fileHash = hashContent(fileBuffer);
4961
+ const baseHash = indexHash || headHash;
4962
+ if (baseHash) {
4963
+ if (fileHash !== indexHash && indexHash) {
4964
+ modifiedFiles.push(relPath);
4965
+ } else if (fileHash !== headHash && !indexHash) {
4966
+ modifiedFiles.push(relPath);
4923
4967
  }
4924
4968
  } else {
4925
- untrackedItems.push({ name: entry.name, type: "file" });
4969
+ untrackedFiles.push(relPath);
4970
+ }
4971
+ } else {
4972
+ if (indexHash || headHash) {
4973
+ if (indexHash) {
4974
+ deletedFiles.push(relPath);
4975
+ }
4926
4976
  }
4927
- } else if (entry.isDirectory()) {
4928
- untrackedItems.push({ name: entry.name, type: "directory" });
4929
4977
  }
4930
4978
  }
4931
- if (stagedFiles.length > 0) {
4979
+ if (stagedAdditions.length > 0 || stagedModifications.length > 0 || stagedDeletions.length > 0) {
4932
4980
  console.log(`
4933
4981
  ${source_default.green("Changes to be committed:")}`);
4934
4982
  console.log(` (use "${source_default.cyan("brch reset")}" to unstage)`);
4935
- for (const file of stagedFiles) {
4936
- console.log(` ${source_default.green("new file:")} ${file}`);
4937
- }
4938
- }
4939
- if (modifiedFiles.length > 0) {
4983
+ for (const file of stagedAdditions)
4984
+ console.log(` ${source_default.green("new file:")} ${file}`);
4985
+ for (const file of stagedModifications)
4986
+ console.log(` ${source_default.green("modified:")} ${file}`);
4987
+ for (const file of stagedDeletions)
4988
+ console.log(` ${source_default.green("deleted:")} ${file}`);
4989
+ }
4990
+ if (modifiedFiles.length > 0 || deletedFiles.length > 0) {
4940
4991
  console.log(`
4941
4992
  ${source_default.red("Changes not staged for commit:")}`);
4942
4993
  console.log(` (use "${source_default.cyan("brch add")}" to stage changes)`);
4943
- for (const file of modifiedFiles) {
4944
- console.log(` ${source_default.red("modified:")} ${file}`);
4945
- }
4994
+ for (const file of modifiedFiles)
4995
+ console.log(` ${source_default.red("modified:")} ${file}`);
4996
+ for (const file of deletedFiles)
4997
+ console.log(` ${source_default.red("deleted:")} ${file}`);
4946
4998
  }
4947
- if (untrackedItems.length > 0) {
4999
+ if (untrackedFiles.length > 0) {
4948
5000
  console.log(`
4949
- ${source_default.red("Untracked files and directories:")}`);
5001
+ ${source_default.red("Untracked files:")}`);
4950
5002
  console.log(` (use "${source_default.cyan("brch add")}" to include in what will be committed)`);
4951
- for (const item of untrackedItems) {
4952
- const suffix = item.type === "directory" ? "/" : "";
4953
- console.log(` ${item.name}${suffix}`);
5003
+ for (const file of untrackedFiles) {
5004
+ console.log(` ${file}`);
4954
5005
  }
4955
5006
  }
4956
- if (modifiedFiles.length === 0 && untrackedItems.length === 0) {
5007
+ if (stagedAdditions.length === 0 && stagedModifications.length === 0 && stagedDeletions.length === 0 && modifiedFiles.length === 0 && deletedFiles.length === 0 && untrackedFiles.length === 0) {
4957
5008
  console.log(source_default.green("nothing to commit, working tree clean"));
4958
5009
  }
4959
5010
  } catch (error) {
@@ -4964,7 +5015,17 @@ ${source_default.red("Untracked files and directories:")}`);
4964
5015
  };
4965
5016
 
4966
5017
  // src/commands/statusCommand.ts
4967
- var statusCommand = new Command("status").description("Show the working tree status").action(async () => {
5018
+ var statusCommand = new Command("status").description("Show the working tree status").addHelpText("after", `
5019
+ Examples:
5020
+ $ brch status
5021
+
5022
+ Displays:
5023
+ - Changes to be committed (staged files)
5024
+ - Changes not staged for commit (modified tracked files)
5025
+ - Untracked files (new files not yet added)
5026
+
5027
+ Use 'brch add <file>...' to stage files for commit.
5028
+ `).action(async () => {
4968
5029
  status();
4969
5030
  });
4970
5031
 
@@ -5789,11 +5850,9 @@ var getTrackedFiles2 = async (commitHash) => {
5789
5850
  try {
5790
5851
  const commitPath = path5.join(OBJECTS_PATH, commitHash.substring(0, 2), commitHash.substring(2));
5791
5852
  const commitData = JSON.parse(await fs5.readFile(commitPath, "utf-8"));
5792
- if (commitData.tree) {
5793
- const treePath = path5.join(OBJECTS_PATH, commitData.tree.substring(0, 2), commitData.tree.substring(2));
5794
- const treeData = JSON.parse(await fs5.readFile(treePath, "utf-8"));
5795
- for (const [file, hash] of Object.entries(treeData)) {
5796
- trackedFiles.set(file, hash);
5853
+ if (commitData.files && Array.isArray(commitData.files)) {
5854
+ for (const entry of commitData.files) {
5855
+ trackedFiles.set(entry.path, entry.hash);
5797
5856
  }
5798
5857
  }
5799
5858
  } catch (error) {}
@@ -5819,7 +5878,29 @@ var colorDiffLine = (line) => {
5819
5878
  }
5820
5879
  return line;
5821
5880
  };
5822
- var diff = async () => {
5881
+ var normalizeRelativePath4 = (pathValue) => {
5882
+ const normalized = pathValue.split("\\").join("/");
5883
+ if (normalized && !normalized.startsWith("./") && !normalized.startsWith("../") && !normalized.startsWith("/")) {
5884
+ return "./" + normalized;
5885
+ }
5886
+ return normalized;
5887
+ };
5888
+ var walk2 = async (dir, repoRoot, ignorePatterns) => {
5889
+ let files = [];
5890
+ const entries = await fs5.readdir(dir, { withFileTypes: true });
5891
+ for (const entry of entries) {
5892
+ const res = path5.resolve(dir, entry.name);
5893
+ if (entry.name === VCS_DIR || shouldIgnore3(entry.name, ignorePatterns))
5894
+ continue;
5895
+ if (entry.isDirectory()) {
5896
+ files = files.concat(await walk2(res, repoRoot, ignorePatterns));
5897
+ } else {
5898
+ files.push(normalizeRelativePath4(path5.relative(repoRoot, res)));
5899
+ }
5900
+ }
5901
+ return files;
5902
+ };
5903
+ var diff = async (filePaths) => {
5823
5904
  try {
5824
5905
  const currentHead = await getCurrentHead();
5825
5906
  const trackedFiles = await getTrackedFiles2(currentHead);
@@ -5828,24 +5909,40 @@ var diff = async () => {
5828
5909
  console.log(source_default.yellow("No commits yet. Nothing to diff."));
5829
5910
  return;
5830
5911
  }
5831
- const workdir = process.cwd();
5832
- const entries = await fs5.readdir(workdir, { withFileTypes: true });
5833
- let hasDiffs = false;
5834
- for (const entry of entries) {
5835
- if (entry.name === VCS_DIR) {
5836
- continue;
5837
- }
5838
- if (shouldIgnore3(entry.name, ignorePatterns)) {
5839
- continue;
5912
+ const repoRoot = process.cwd();
5913
+ let filesToCompare = [];
5914
+ if (filePaths && filePaths.length > 0) {
5915
+ for (const p of filePaths) {
5916
+ const absolutePath = path5.resolve(repoRoot, p);
5917
+ try {
5918
+ const stats = await fs5.stat(absolutePath);
5919
+ if (stats.isDirectory()) {
5920
+ const dirFiles = await walk2(absolutePath, repoRoot, ignorePatterns);
5921
+ filesToCompare.push(...dirFiles);
5922
+ } else {
5923
+ const relativeToRoot = path5.relative(repoRoot, absolutePath);
5924
+ filesToCompare.push(normalizeRelativePath4(relativeToRoot));
5925
+ }
5926
+ } catch (error) {
5927
+ const relativeToRoot = path5.relative(repoRoot, absolutePath);
5928
+ filesToCompare.push(normalizeRelativePath4(relativeToRoot));
5929
+ }
5840
5930
  }
5841
- if (entry.isFile()) {
5842
- const filePath = path5.join(workdir, entry.name);
5843
- const fileHash = hashContent(filePath);
5844
- const trackedHash = trackedFiles.get(entry.name);
5931
+ filesToCompare = [...new Set(filesToCompare)];
5932
+ } else {
5933
+ filesToCompare = await walk2(repoRoot, repoRoot, ignorePatterns);
5934
+ }
5935
+ let hasDiffs = false;
5936
+ for (const relPath of filesToCompare) {
5937
+ try {
5938
+ const fullPath = path5.join(repoRoot, relPath);
5939
+ const fileBuffer = await fs5.readFile(fullPath);
5940
+ const fileHash = hashContent(fileBuffer);
5941
+ const trackedHash = trackedFiles.get(relPath);
5845
5942
  if (trackedHash && fileHash !== trackedHash) {
5846
5943
  const oldContent = await getFileContentFromHash(trackedHash);
5847
- const newContent = await fs5.readFile(filePath, "utf-8");
5848
- const patch = createTwoFilesPatch(`a/${entry.name}`, `b/${entry.name}`, oldContent, newContent, "HEAD", "Working Directory");
5944
+ const newContent = fileBuffer.toString("utf-8");
5945
+ const patch = createTwoFilesPatch(`a/${relPath}`, `b/${relPath}`, oldContent, newContent, "HEAD", "Working Directory");
5849
5946
  const lines = patch.split(`
5850
5947
  `);
5851
5948
  for (const line of lines) {
@@ -5854,7 +5951,7 @@ var diff = async () => {
5854
5951
  console.log("");
5855
5952
  hasDiffs = true;
5856
5953
  }
5857
- }
5954
+ } catch (error) {}
5858
5955
  }
5859
5956
  if (!hasDiffs) {
5860
5957
  console.log(source_default.green("No changes detected."));
@@ -5867,8 +5964,16 @@ var diff = async () => {
5867
5964
  };
5868
5965
 
5869
5966
  // src/commands/diffCommand.ts
5870
- var diffCommand = new Command("diff").description("Show changes between working directory and last commit").action(async () => {
5871
- await diff();
5967
+ var diffCommand = new Command("diff").description("Show changes between working directory and last commit").argument("[files...]", "Specific files to show differences for").addHelpText("after", `
5968
+ Examples:
5969
+ $ brch diff Show changes for all modified files
5970
+ $ brch diff file.txt Show changes for a specific file
5971
+ $ brch diff src/ Show changes for all files in a directory
5972
+
5973
+ Displays line-by-line differences between your current files and the last committed version.
5974
+ Deleted lines are shown in red, and added lines are shown in green.
5975
+ `).action(async (files) => {
5976
+ await diff(files);
5872
5977
  });
5873
5978
 
5874
5979
  // src/commands/index.ts
@@ -5887,10 +5992,11 @@ program.name(VCS_NAME).description("brch - A simple version control system for t
5887
5992
  Examples:
5888
5993
  $ brch init Initialize a new repository
5889
5994
  $ brch add . Stage all files in current directory
5890
- $ brch add file1.txt file2.js Stage specific files
5891
- $ brch commit -m "Initial commit" Commit staged changes
5995
+ $ brch status Show current repository status
5996
+ $ brch commit -m "Commit msg" Commit staged changes
5997
+ $ brch log Show commit history
5998
+ $ brch diff Show changes in working tree
5892
5999
  $ brch config set user.name "John Doe" Set configuration
5893
- $ brch config set user.email "john@example.com" --global Set global configuration
5894
6000
 
5895
6001
  For more information about a specific command, use:
5896
6002
  $ brch <command> --help
@@ -1 +1 @@
1
- export declare const diff: () => Promise<void>;
1
+ export declare const diff: (filePaths?: string[]) => Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "brch",
3
- "version": "0.0.2",
4
- "description": "A simple VCS",
3
+ "version": "0.0.3",
4
+ "description": "brch - A simple version control system for tracking changes in your project",
5
5
  "author": "vishalkrsharma",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -0,0 +1 @@
1
+ vishal kumar sharma