internal virtual T Compare <T>(DiffModifiers diffOptions, IEnumerable <string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) where T : class { Func <DiffSafeHandle, object> builder; if (!ChangesBuilders.TryGetValue(typeof(T), out builder)) { throw new LibGit2SharpException(string.Format(CultureInfo.InvariantCulture, "Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.", typeof(T), typeof(TreeChanges), typeof(Patch))); } var comparer = WorkdirToIndex(repo); if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } using (DiffSafeHandle diff = BuildDiffList(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)) { return((T)builder(diff)); } }
private DiffSafeHandle BuildDiffList(ObjectId oldTreeId, ObjectId newTreeId, TreeComparisonHandleRetriever comparisonHandleRetriever, DiffModifiers diffOptions, IEnumerable <string> paths, ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) { var matchedPaths = new MatchedPathsAggregator(); var filePaths = repo.ToFilePaths(paths); using (GitDiffOptions options = BuildOptions(diffOptions, filePaths, matchedPaths, compareOptions)) { var diffList = comparisonHandleRetriever(oldTreeId, newTreeId, options); if (explicitPathsOptions != null) { try { DispatchUnmatchedPaths(explicitPathsOptions, filePaths, matchedPaths); } catch { diffList.Dispose(); throw; } } DetectRenames(diffList, compareOptions); return(diffList); } }
/// <summary> /// Show changes between a <see cref="Tree"/> and the Index, the Working Directory, or both. /// <para> /// The level of diff performed can be specified by passing either a <see cref="TreeChanges"/> /// or <see cref="Patch"/> type as the generic parameter. /// </para> /// </summary> /// <param name="oldTree">The <see cref="Tree"/> to compare from.</param> /// <param name="diffTargets">The targets to compare to.</param> /// <param name="paths">The list of paths (either files or directories) that should be compared.</param> /// <param name="explicitPathsOptions"> /// If set, the passed <paramref name="paths"/> will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// </param> /// <param name="compareOptions">Additional options to define patch generation behavior.</param> /// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or /// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam> /// <returns>A <typeparamref name="T"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns> public virtual T Compare <T>(Tree oldTree, DiffTargets diffTargets, IEnumerable <string> paths, ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) where T : class, IDiffResult { var comparer = HandleRetrieverDispatcher[diffTargets](repo); ObjectId oldTreeId = oldTree != null ? oldTree.Id : null; DiffModifiers diffOptions = diffTargets.HasFlag(DiffTargets.WorkingDirectory) ? DiffModifiers.IncludeUntracked : DiffModifiers.None; if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } using (DiffSafeHandle diff = BuildDiffList(oldTreeId, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)) { return(BuildDiffResult <T>(diff)); } }
internal virtual T Compare <T>( DiffModifiers diffOptions, IEnumerable <string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) where T : class, IDiffResult { var comparer = WorkdirToIndex(repo); if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } DiffHandle diff = BuildDiffList(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); try { return(BuildDiffResult <T>(diff)); } catch { diff.SafeDispose(); throw; } }
private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[] filePaths = null, MatchedPathsAggregator matchedPathsAggregator = null, CompareOptions compareOptions = null) { var options = new GitDiffOptions(); options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_TYPECHANGE; compareOptions = compareOptions ?? new CompareOptions(); options.ContextLines = (ushort)compareOptions.ContextLines; options.InterhunkLines = (ushort)compareOptions.InterhunkLines; if (diffOptions.HasFlag(DiffModifiers.IncludeUntracked)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED | GitDiffOptionFlags.GIT_DIFF_RECURSE_UNTRACKED_DIRS | GitDiffOptionFlags.GIT_DIFF_SHOW_UNTRACKED_CONTENT; } if (diffOptions.HasFlag(DiffModifiers.IncludeIgnored)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_IGNORED | GitDiffOptionFlags.GIT_DIFF_RECURSE_IGNORED_DIRS; } if (diffOptions.HasFlag(DiffModifiers.IncludeUnmodified) || compareOptions.IncludeUnmodified || (compareOptions.Similarity != null && (compareOptions.Similarity.RenameDetectionMode == RenameDetectionMode.CopiesHarder || compareOptions.Similarity.RenameDetectionMode == RenameDetectionMode.Exact))) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNMODIFIED; } if (compareOptions.Algorithm == DiffAlgorithm.Patience) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_PATIENCE; } else if (compareOptions.Algorithm == DiffAlgorithm.Minimal) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_MINIMAL; } if (diffOptions.HasFlag(DiffModifiers.DisablePathspecMatch)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH; } if (matchedPathsAggregator != null) { options.NotifyCallback = matchedPathsAggregator.OnGitDiffNotify; } if (filePaths != null) { options.PathSpec = GitStrArrayManaged.BuildFrom(filePaths); } return(options); }
private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[] filePaths = null, MatchedPathsAggregator matchedPathsAggregator = null, CompareOptions compareOptions = null) { var options = new GitDiffOptions(); options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_TYPECHANGE; compareOptions = compareOptions ?? new CompareOptions(); options.ContextLines = (ushort)compareOptions.ContextLines; options.InterhunkLines = (ushort)compareOptions.InterhunkLines; if (diffOptions.HasFlag(DiffModifiers.IncludeUntracked)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED | GitDiffOptionFlags.GIT_DIFF_RECURSE_UNTRACKED_DIRS | GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; } if (diffOptions.HasFlag(DiffModifiers.IncludeIgnored)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_IGNORED | GitDiffOptionFlags.GIT_DIFF_RECURSE_IGNORED_DIRS; } if (diffOptions.HasFlag(DiffModifiers.IncludeUnmodified)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNMODIFIED; } if (diffOptions.HasFlag(DiffModifiers.DisablePathspecMatch)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH; } if (matchedPathsAggregator != null) { options.NotifyCallback = matchedPathsAggregator.OnGitDiffNotify; } if (filePaths == null) { return(options); } options.PathSpec = GitStrArrayIn.BuildFrom(filePaths); return(options); }
private DiffHandle BuildDiffList( ObjectId oldTreeId, ObjectId newTreeId, TreeComparisonHandleRetriever comparisonHandleRetriever, DiffModifiers diffOptions, IEnumerable <string> paths, ExplicitPathsOptions explicitPathsOptions, CompareOptions compareOptions) { var filePaths = repo.ToFilePaths(paths); MatchedPathsAggregator matchedPaths = null; // We can't match paths unless we've got something to match // against and we're told to do so. if (filePaths != null && explicitPathsOptions != null) { if (explicitPathsOptions.OnUnmatchedPath != null || explicitPathsOptions.ShouldFailOnUnmatchedPath) { matchedPaths = new MatchedPathsAggregator(); } } using (GitDiffOptions options = BuildOptions(diffOptions, filePaths, matchedPaths, compareOptions)) { var diffList = comparisonHandleRetriever(oldTreeId, newTreeId, options); if (matchedPaths != null) { try { DispatchUnmatchedPaths(explicitPathsOptions, filePaths, matchedPaths); } catch { diffList.Dispose(); throw; } } DetectRenames(diffList, compareOptions); return(diffList); } }
internal virtual TreeChanges Compare(DiffModifiers diffOptions, IEnumerable <string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var comparer = WorkdirToIndex(repo); if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } return(BuildTreeChangesFromComparer(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)); }
private TreeChanges BuildTreeChangesFromComparer( ObjectId oldTreeId, ObjectId newTreeId, TreeComparisonHandleRetriever comparisonHandleRetriever, DiffModifiers diffOptions, IEnumerable <string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var matchedPaths = new MatchedPathsAggregator(); var filePaths = repo.ToFilePaths(paths); using (GitDiffOptions options = BuildOptions(diffOptions, filePaths, matchedPaths, compareOptions)) using (DiffListSafeHandle diffList = comparisonHandleRetriever(oldTreeId, newTreeId, options)) { if (explicitPathsOptions != null) { DispatchUnmatchedPaths(explicitPathsOptions, filePaths, matchedPaths); } return(new TreeChanges(diffList)); } }
/// <summary> /// Show changes between a <see cref="Tree"/> and the Index, the Working Directory, or both. /// </summary> /// <param name="oldTree">The <see cref="Tree"/> to compare from.</param> /// <param name="diffTargets">The targets to compare to.</param> /// <param name="paths">The list of paths (either files or directories) that should be compared.</param> /// <param name="explicitPathsOptions"> /// If set, the passed <paramref name="paths"/> will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// </param> /// <param name="compareOptions">Additional options to define comparison behavior.</param> /// <returns>A <see cref="TreeChanges"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns> public virtual TreeChanges Compare(Tree oldTree, DiffTargets diffTargets, IEnumerable <string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var comparer = handleRetrieverDispatcher[diffTargets](repo); ObjectId oldTreeId = oldTree != null ? oldTree.Id : null; DiffModifiers diffOptions = diffTargets.HasFlag(DiffTargets.WorkingDirectory) ? DiffModifiers.IncludeUntracked : DiffModifiers.None; if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } return(BuildTreeChangesFromComparer(oldTreeId, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)); }
/// <summary> /// Promotes to the staging area the latest modifications of a collection of files in the working directory (addition, updation or removal). /// /// Any paths (even those listed explicitly) that are ignored by configuration will not be staged unless <see cref="StageOptions.IncludeIgnored"/> is unset. /// </summary> /// <param name="paths">The collection of paths of the files within the working directory.</param> /// <param name="stageOptions">If set, determines how paths will be staged.</param> public virtual void Stage(IEnumerable <string> paths, StageOptions stageOptions = null) { Ensure.ArgumentNotNull(paths, "paths"); DiffModifiers diffModifiers = DiffModifiers.IncludeUntracked; ExplicitPathsOptions explicitPathsOptions = stageOptions != null ? stageOptions.ExplicitPathsOptions : null; if (stageOptions != null && stageOptions.IncludeIgnored) { diffModifiers |= DiffModifiers.IncludeIgnored; } var changes = repo.Diff.Compare <TreeChanges>(diffModifiers, paths, explicitPathsOptions); foreach (var treeEntryChanges in changes) { switch (treeEntryChanges.Status) { case ChangeKind.Unmodified: continue; case ChangeKind.Deleted: RemoveFromIndex(treeEntryChanges.Path); continue; case ChangeKind.Added: /* Fall through */ case ChangeKind.Modified: AddToIndex(treeEntryChanges.Path); continue; default: throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "Entry '{0}' bears an unexpected ChangeKind '{1}'", treeEntryChanges.Path, treeEntryChanges.Status)); } } UpdatePhysicalIndex(); }
/// <summary> /// Show changes between a <see cref="Tree"/> and the Index, the Working Directory, or both. /// <para> /// The level of diff performed can be specified by passing either a <see cref="TreeChanges"/> /// or <see cref="Patch"/> type as the generic parameter. /// </para> /// </summary> /// <param name="oldTree">The <see cref="Tree"/> to compare from.</param> /// <param name="diffTargets">The targets to compare to.</param> /// <param name="paths">The list of paths (either files or directories) that should be compared.</param> /// <param name="explicitPathsOptions"> /// If set, the passed <paramref name="paths"/> will be treated as explicit paths. /// Use these options to determine how unmatched explicit paths should be handled. /// </param> /// <param name="compareOptions">Additional options to define patch generation behavior.</param> /// <typeparam name="T">Can be either a <see cref="TreeChanges"/> if you are only interested in the list of files modified, added, ..., or /// a <see cref="Patch"/> if you want the actual patch content for the whole diff and for individual files.</typeparam> /// <returns>A <typeparamref name="T"/> containing the changes between the <see cref="Tree"/> and the selected target.</returns> public virtual T Compare <T>(Tree oldTree, DiffTargets diffTargets, IEnumerable <string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) where T : class { Func <DiffSafeHandle, object> builder; if (!ChangesBuilders.TryGetValue(typeof(T), out builder)) { throw new LibGit2SharpException(string.Format(CultureInfo.InvariantCulture, "Unexpected type '{0}' passed to Compare. Supported values are either '{1}' or '{2}'.", typeof(T), typeof(TreeChanges), typeof(Patch))); } var comparer = HandleRetrieverDispatcher[diffTargets](repo); ObjectId oldTreeId = oldTree != null ? oldTree.Id : null; DiffModifiers diffOptions = diffTargets.HasFlag(DiffTargets.WorkingDirectory) ? DiffModifiers.IncludeUntracked : DiffModifiers.None; if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } using (DiffSafeHandle diff = BuildDiffList(oldTreeId, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions)) { return((T)builder(diff)); } }
/// <summary> /// Promotes to the staging area the latest modifications of a collection of files in the working directory (addition, updation or removal). /// /// Any paths (even those listed explicitly) that are ignored by configuration will not be staged unless <see cref="StageOptions.IncludeIgnored"/> is unset. /// </summary> /// <param name="repository">The repository in which to act</param> /// <param name="paths">The collection of paths of the files within the working directory.</param> /// <param name="stageOptions">Determines how paths will be staged.</param> public static void Stage(IRepository repository, IEnumerable <string> paths, StageOptions stageOptions) { Ensure.ArgumentNotNull(repository, "repository"); Ensure.ArgumentNotNull(paths, "paths"); DiffModifiers diffModifiers = DiffModifiers.IncludeUntracked; ExplicitPathsOptions explicitPathsOptions = stageOptions != null ? stageOptions.ExplicitPathsOptions : null; if (stageOptions != null && stageOptions.IncludeIgnored) { diffModifiers |= DiffModifiers.IncludeIgnored; } using (var changes = repository.Diff.Compare <TreeChanges>(diffModifiers, paths, explicitPathsOptions, new CompareOptions { Similarity = SimilarityOptions.None })) { var unexpectedTypesOfChanges = changes .Where( tec => tec.Status != ChangeKind.Added && tec.Status != ChangeKind.Modified && tec.Status != ChangeKind.Conflicted && tec.Status != ChangeKind.Unmodified && tec.Status != ChangeKind.Deleted).ToList(); if (unexpectedTypesOfChanges.Count > 0) { throw new InvalidOperationException( string.Format(CultureInfo.InvariantCulture, "Entry '{0}' bears an unexpected ChangeKind '{1}'", unexpectedTypesOfChanges[0].Path, unexpectedTypesOfChanges[0].Status)); } /* Remove files from the index that don't exist on disk */ foreach (TreeEntryChanges treeEntryChanges in changes) { switch (treeEntryChanges.Status) { case ChangeKind.Conflicted: if (!treeEntryChanges.Exists) { repository.Index.Remove(treeEntryChanges.Path); } break; case ChangeKind.Deleted: repository.Index.Remove(treeEntryChanges.Path); break; default: continue; } } foreach (TreeEntryChanges treeEntryChanges in changes) { switch (treeEntryChanges.Status) { case ChangeKind.Added: case ChangeKind.Modified: repository.Index.Add(treeEntryChanges.Path); break; case ChangeKind.Conflicted: if (treeEntryChanges.Exists) { repository.Index.Add(treeEntryChanges.Path); } break; default: continue; } } repository.Index.Write(); } }
private TreeChanges BuildTreeChangesFromComparer( ObjectId oldTreeId, ObjectId newTreeId, TreeComparisonHandleRetriever comparisonHandleRetriever, DiffModifiers diffOptions, IEnumerable<string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var matchedPaths = new MatchedPathsAggregator(); var filePaths = repo.ToFilePaths(paths); using (GitDiffOptions options = BuildOptions(diffOptions, filePaths, matchedPaths, compareOptions)) using (DiffListSafeHandle diffList = comparisonHandleRetriever(oldTreeId, newTreeId, options)) { if (explicitPathsOptions != null) { DispatchUnmatchedPaths(explicitPathsOptions, filePaths, matchedPaths); } return new TreeChanges(diffList); } }
private static GitDiffOptions BuildOptions(DiffModifiers diffOptions, FilePath[] filePaths = null, MatchedPathsAggregator matchedPathsAggregator = null, CompareOptions compareOptions = null) { var options = new GitDiffOptions(); options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_TYPECHANGE; compareOptions = compareOptions ?? new CompareOptions(); options.ContextLines = (ushort)compareOptions.ContextLines; options.InterhunkLines = (ushort)compareOptions.InterhunkLines; if (diffOptions.HasFlag(DiffModifiers.IncludeUntracked)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED | GitDiffOptionFlags.GIT_DIFF_RECURSE_UNTRACKED_DIRS | GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNTRACKED_CONTENT; } if (diffOptions.HasFlag(DiffModifiers.IncludeIgnored)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_IGNORED; } if (diffOptions.HasFlag(DiffModifiers.IncludeUnmodified)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_INCLUDE_UNMODIFIED; } if (diffOptions.HasFlag(DiffModifiers.DisablePathspecMatch)) { options.Flags |= GitDiffOptionFlags.GIT_DIFF_DISABLE_PATHSPEC_MATCH; } if (matchedPathsAggregator != null) { options.NotifyCallback = matchedPathsAggregator.OnGitDiffNotify; } if (filePaths == null) { return options; } options.PathSpec = GitStrArrayIn.BuildFrom(filePaths); return options; }
internal virtual TreeChanges Compare(DiffModifiers diffOptions, IEnumerable<string> paths = null, ExplicitPathsOptions explicitPathsOptions = null, CompareOptions compareOptions = null) { var comparer = WorkdirToIndex(repo); if (explicitPathsOptions != null) { diffOptions |= DiffModifiers.DisablePathspecMatch; if (explicitPathsOptions.ShouldFailOnUnmatchedPath || explicitPathsOptions.OnUnmatchedPath != null) { diffOptions |= DiffModifiers.IncludeUnmodified; } } return BuildTreeChangesFromComparer(null, null, comparer, diffOptions, paths, explicitPathsOptions, compareOptions); }