/// <summary> /// Unstage overwrites staged files in the index with their current version in HEAD. In case of newly added files they are removed from the index. /// </summary> /// <param name="paths">Relative paths to files you want to unstage.</param> public void Unstage(params string[] paths) { GitIndex.RereadIfNecessary(); foreach (var absolute_or_relative_path in paths) { string path = absolute_or_relative_path; if (Path.IsPathRooted(absolute_or_relative_path)) { path = Core.Util.PathUtil.RelativePath(_repo.WorkingDirectory, absolute_or_relative_path); } if (this[path] == null) { return; } var blob = _repo.Get <Leaf>(path); // <--- we wouldn't want to stage something that is not representing a file if (blob == null) { GitIndex.Remove(path); } else { GitIndex.add(Core.Repository.GitInternalSlash(PathEncoding.GetBytes(path)), blob.RawData); } } GitIndex.write(); }
/// <summary> /// Removes files or directories from the index and delete them from the working directory. /// /// </summary> /// <param name="paths"></param> public void Delete(params string[] paths) { GitIndex.RereadIfNecessary(); foreach (var absolute_or_relative_path in paths) { string path = absolute_or_relative_path; if (!Path.IsPathRooted(absolute_or_relative_path)) { path = Path.Combine(_repo.WorkingDirectory, path); } if (new FileInfo(path).Exists) { RemoveFile(new FileInfo(path), true); } else if (new DirectoryInfo(path).Exists) { RemoveDirectory(new DirectoryInfo(path), true); } else { throw new ArgumentException("File or directory at <" + path + "> doesn't seem to exist.", "path"); } } GitIndex.write(); }
/// <summary> /// Removes files or directories from the index which are no longer to be tracked. /// Does not delete files from the working directory. Use <seealso cref="Delete"/> to remove and delete files. /// </summary> /// <param name="paths"></param> public void Remove(params string[] paths) { GitIndex.RereadIfNecessary(); foreach (var absolute_or_relative_path in paths) { string path = absolute_or_relative_path; string relative_path = absolute_or_relative_path; if (!Path.IsPathRooted(absolute_or_relative_path)) { path = Path.Combine(_repo.WorkingDirectory, absolute_or_relative_path); } else { relative_path = Core.Util.PathUtil.RelativePath(_repo.WorkingDirectory, absolute_or_relative_path); } if (new FileInfo(path).Exists) { RemoveFile(new FileInfo(path), false); } else if (new DirectoryInfo(path).Exists) { RemoveDirectory(new DirectoryInfo(path), false); } else { GitIndex.Remove(relative_path); } } GitIndex.write(); }
private void UpdateSingleFile(string file) { TreeEntry treeEntry = null; var commit = Repository.Head.CurrentCommit; _tree = commit != null ? commit.Tree : null; if (_tree != null) { treeEntry = _tree.FindBlobMember(file); } _index = Repository.Index.GitIndex; _index.RereadIfNecessary(); GitIndex.Entry indexEntry = _index.GetEntry(file); TreeEntry wdirEntry = null; FileInfo fileInfo = new FileInfo(Path.Combine(Repository.WorkingDirectory, file.Replace('/', Path.DirectorySeparatorChar))); if (fileInfo.Exists && !IgnoreHandler.IsIgnored(file)) { var tree = new Core.Tree(Repository._internal_repo); wdirEntry = tree.AddFile(file); } OnVisitEntry(treeEntry, wdirEntry, indexEntry, fileInfo); }
public Stash Create(string message) { var parent = _repo.CurrentBranch.CurrentCommit; Author author = new Author(_repo.Config["user.name"] ?? "unknown", _repo.Config["user.email"] ?? "unknown@(none)."); if (message == null) { // Use the commit summary as message message = parent.ShortHash + " " + parent.Message; int i = message.IndexOfAny(new char[] { '\r', '\n' }); if (i != -1) { message = message.Substring(0, i); } } // Create the index tree commit GitIndex index = _repo.Index.GitIndex; index.RereadIfNecessary(); var tree_id = index.writeTree(); Tree indexTree = new Tree(_repo, tree_id); string commitMsg = "index on " + _repo.CurrentBranch.Name + ": " + message; var indexCommit = Commit.Create(commitMsg + "\n", parent, indexTree, author); // Create the working dir commit tree_id = WriteWorkingDirectoryTree(parent.Tree.InternalTree, index); commitMsg = "WIP on " + _repo.CurrentBranch.Name + ": " + message; var wipCommit = Commit.Create(commitMsg + "\n", new Commit[] { parent, indexCommit }, new Tree(_repo, tree_id), author, author, DateTimeOffset.Now); string prevCommit = null; FileInfo sf = StashRefFile; if (sf.Exists) { prevCommit = File.ReadAllText(sf.FullName); } Stash s = new Stash(prevCommit, wipCommit.Hash, author, commitMsg); FileInfo stashLog = StashLogFile; File.AppendAllText(stashLog.FullName, s.FullLine + "\n"); File.WriteAllText(sf.FullName, s.CommitId + "\n"); // Wipe all local changes _repo.CurrentBranch.Reset(ResetBehavior.Hard); s.StashCollection = this; return(s); }
/// <summary> /// Run the diff operation. Until this is called, all lists will be empty /// </summary> /// <returns>true if anything is different between index, tree, and workdir</returns> private void UpdateDirectoryRecursive(string path) { var commit = Repository.Head.CurrentCommit; _tree = (commit != null ? commit.Tree : new Core.Tree(Repository)); _index = Repository.Index.GitIndex; _index.RereadIfNecessary(); DirectoryInfo root = _index.Repository.WorkingDirectory; var visitor = new AbstractIndexTreeVisitor { VisitEntryAux = OnVisitEntry }; new IndexTreeWalker(_index, _tree, CreateWorkingDirectoryTree(path), root, visitor).Walk(); }
/// <summary> /// Check out given paths from the index overwriting files in the working directory. Modified files might be overwritten. /// </summary> /// <param name="paths"></param> public void Checkout(params string[] paths) { GitIndex.RereadIfNecessary(); foreach (var absolute_or_relative_path in paths) { string path = absolute_or_relative_path; if (Path.IsPathRooted(absolute_or_relative_path)) { path = Core.Util.PathUtil.RelativePath(_repo.WorkingDirectory, absolute_or_relative_path); } var e = GitIndex.GetEntry(path); if (e == null) { continue; } GitIndex.checkoutEntry(new FileInfo(_repo.WorkingDirectory), e); } }
public Commit CommitChanges(string message, Author author) { if (string.IsNullOrEmpty(message)) { throw new ArgumentException("Commit message must not be null or empty!", "message"); } if (string.IsNullOrEmpty(author.Name)) { throw new ArgumentException("Author name must not be null or empty!", "author"); } GitIndex.RereadIfNecessary(); var tree_id = GitIndex.writeTree(); // check if tree is different from current commit's tree var parent = _repo.CurrentBranch.CurrentCommit; if ((parent == null && GitIndex.Members.Count == 0) || (parent != null && parent.Tree._id == tree_id)) { throw new InvalidOperationException("There are no changes to commit"); } var commit = Commit.Create(message, parent, new Tree(_repo, tree_id), author); Ref.Update("HEAD", commit); return(commit); }
// [henon] we do not publicly expose checking out into a custom directory, as this is an unrealistic use case and conflicts with checking out paths. // it is possible anyway by iterating over the Entries and writing the contents of each entry into a custom directory! private void Checkout(string directory) { GitIndex.RereadIfNecessary(); GitIndex.checkout(new FileInfo(directory)); }