public void IsCommitAncestor_returns_false_is_descendant_and_ancestor_are_swapped()
        {
            string ancestorId;
            string descandantId;

            // create 2 commits on master branch
            using (var workingDirectory = new TemporaryWorkingDirectory(m_TempDirectory.Location, "master"))
            {
                File.WriteAllText(Path.Combine(workingDirectory.Location, "file1.txt"), "Irrelevant");
                ancestorId = workingDirectory.Commit("Commit1");

                File.WriteAllText(Path.Combine(workingDirectory.Location, "file2.txt"), "Irrelevant");
                descandantId = workingDirectory.Commit("Commit1");

                workingDirectory.Push();
            }
            
            Assert.False(m_Repository.IsCommitAncestor(descandantId, ancestorId));
        }
示例#2
0
        public void Repository_with_subdirectories()
        {
            // arrange
            string commitId;
            using (var workingDirectory = new TemporaryWorkingDirectory(m_Repository.Directory.Location, "master"))
            {                
                var directory = new Directory(Path.GetFileName(workingDirectory.Location))
                {
                    root => new Directory(root, s_Dir1)
                    {
                        dir1 => new EmptyFile(dir1, s_File1),
                        dir1 => new EmptyFile(dir1, s_File2)
                    },
                    root => new Directory(root, s_Dir2)
                    {
                        dir2 => new EmptyFile(dir2, s_File1)
                    }
                };

                System.IO.File.Delete(Path.Combine(workingDirectory.Location, RepositoryInfoFile.RepositoryInfoFileName));

                m_DirectoryCreator.CreateDirectory(directory, Path.GetDirectoryName(workingDirectory.Location));
                commitId = workingDirectory.Commit();
                workingDirectory.Push();
            }

            using (var repo = new Repository(m_Repository.Directory.Location))
            {
                // act
                var commit = repo.Lookup<Commit>(commitId);
                var gitDirectory = new GitDirectory(null, m_Repository.Directory.Name, commit);


                // assert
                Assert.Equal(m_Repository.Directory.Name, gitDirectory.Name);

                Assert.Equal(2, gitDirectory.Directories.Count());
                Assert.Empty(gitDirectory.Files);

                Assert.True(gitDirectory.DirectoryExists(s_Dir1));
                Assert.True(gitDirectory.GetDirectory(s_Dir1).FileExists(s_File1));
                Assert.True(gitDirectory.GetDirectory(s_Dir1).FileExists(s_File2));
                Assert.True(gitDirectory.DirectoryExists(s_Dir2));
                Assert.True(gitDirectory.GetDirectory(s_Dir2).FileExists(s_File1));
                
            }

        }
        public void IsCommitAncestor_returns_false_if_commits_are_from_different_branches()
        {
            m_Repository.CreateBranch("branch1", m_Repository.Commits.Single());
            m_Repository.CreateBranch("branch2", m_Repository.Commits.Single());

            string ancestorId;
            using (var workingDirectory = new TemporaryWorkingDirectory(m_TempDirectory.Location, "branch1"))
            {
                File.WriteAllText(Path.Combine(workingDirectory.Location, "file1.txt"), "Irrelevant");
                ancestorId = workingDirectory.Commit("Commit1");                
                workingDirectory.Push();
            }
        
            string descandantId;
            using (var workingDirectory = new TemporaryWorkingDirectory(m_TempDirectory.Location, "branch2"))
            {
                File.WriteAllText(Path.Combine(workingDirectory.Location, "file1.txt"), "Irrelevant");
                descandantId = workingDirectory.Commit("Commit2");
                workingDirectory.Push();
            }
            
            Assert.False(m_Repository.IsCommitAncestor(ancestorId, descandantId));
            Assert.False(m_Repository.IsCommitAncestor(descandantId, ancestorId));
        }
        public void Commit_creates_a_new_commit()
        {
            using (var instance = new TemporaryWorkingDirectory(m_MasterRepository.Directory.Location, "master"))
            {
                CreateFile(instance, "file2.txt");

                var originalCommitCount = GetCommitCount(instance.Location, "master");
           
                instance.Commit();

                var newCommitCount = GetCommitCount(instance.Location, "master");

                Assert.Equal(originalCommitCount +1, newCommitCount);
            }

        }
        public void HasChanges_Returns_False_after_Commit()
        {
            using (var instance = new TemporaryWorkingDirectory(m_MasterRepository.Directory.Location, "master"))
            {
                CreateFile(instance, "file2.txt");

                instance.Commit();

                Assert.False(instance.HasChanges);
            }
        }
示例#6
0
        public void RemoveItems(IEnumerable<SyncAction> syncActions)
        {
            syncActions = syncActions.ToList();

            if (!syncActions.Any())
            {
                return;
            }

            // make sure all to be updated actions exist (otherwise we cannot remove them)
            AssertSyncActionsExist(syncActions, true);

            using (var workingDir = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, BranchName.ToString()))
            {
                var localDirectory = new LocalDirectory(null, workingDir.Location);

                // delete the file                 
                foreach (var syncAction in syncActions)
                {
                    PathValidator.EnsureIsRootedPath(syncAction.Path);

                    var directory = localDirectory.GetDirectory(GetRelativeSyncActionDirectoryPath(syncAction));
                    var file = (ILocalFile) directory.GetFile(SyncActionFile.GetFileName(syncAction));
                    System.IO.File.Delete(file.Location);
                }

                workingDir.Commit($"{nameof(GitSyncActionService)}: Removed {syncActions.Count()} items");
                workingDir.Push();
            }
        }
示例#7
0
        public void UpdateItems(IEnumerable<SyncAction> syncActions)
        {
            syncActions = syncActions.ToList();

            if (!syncActions.Any())
            {
                return;
            }

            // make sure all to be updated actions exist (no need to check the state, this property might have changed)
            AssertSyncActionsExist(syncActions, false);
            
            using (var workingDir = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, BranchName.ToString()))
            {
                var root = new Directory(null, "root");

                foreach (var syncAction in syncActions)
                {
                    PathValidator.EnsureIsRootedPath(syncAction.Path);

                    // remove existing files for this sync action
                    var filesToDelete = Enum.GetValues(typeof (SyncActionState)).Cast<SyncActionState>()
                        .Where(state => state != syncAction.State)
                        .Select(state => GetRelativeSyncActionDirectoryPath(state, syncAction.Path))
                        .Select(relativeDirectoryPath => Path.Combine(relativeDirectoryPath, SyncActionFile.GetFileName(syncAction)))
                        .Select(relativePath => Path.Combine(workingDir.Location, relativePath))
                        .Where(System.IO.File.Exists).ToList();

                    foreach (var file in filesToDelete)
                    {
                        System.IO.File.Delete(file);
                    }

                    // add a new file
                    var directory = DirectoryHelper.GetOrAddDirectory(root, GetRelativeSyncActionDirectoryPath(syncAction));
                    directory.Add(d => new SyncActionFile(d, syncAction));
                }

                var localItemCreator = new LocalItemCreator();
                localItemCreator.CreateDirectoryInPlace(root, workingDir.Location);

                workingDir.Commit($"{nameof(GitSyncActionService)}: Updated {syncActions.Count()} items");
                workingDir.Push();
            }
        }
示例#8
0
        public void AddItems(IEnumerable<SyncAction> syncActions)
        {
            syncActions = syncActions.ToArray();

            if (!syncActions.Any())
            {
                return;
            }

            // make sure, the action does not already exist
            foreach (var action in syncActions)
            {
                var exisitingActions = this[action.State, action.Path].Where(a => a.Id == action.Id);
                if (exisitingActions.Any())
                {
                    throw new DuplicateSyncActionException($"A sync action with id {action.Id} already exists");
                }
            }

            // create the branch if it does not already exist
            EnsureBranchExists();

            // create a file system tree for the actions
            var root = new Directory(null, "root");
            foreach (var syncAction in syncActions)
            {
                PathValidator.EnsureIsRootedPath(syncAction.Path);

                var directory = DirectoryHelper.GetOrAddDirectory(root, GetRelativeSyncActionDirectoryPath(syncAction));
                directory.Add(d => new SyncActionFile(d, syncAction));
            }


            // store the actions
            using (var workingDir = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, BranchName.ToString()))
            {               
                // create the actions on disk
                var localItemCreator = new LocalItemCreator();
                localItemCreator.CreateDirectoryInPlace(root, workingDir.Location);

                // commit (no check if there are pending changes, because there will always be changes (we made sure that syncActions is not empty and action do not yet exist))
                workingDir.Commit($"{nameof(GitSyncActionService)}: Added {syncActions.Count()} items");
                workingDir.Push();
            }
        }
        public void UpdateItem(SyncFolder folder)
        {
            if (folder == null)
            {
                throw new ArgumentNullException(nameof(folder));
            }

            if (!ItemExists(folder.Name))
            {
                throw new SyncFolderNotFoundException($"A sync folder named '{folder.Name}' could not be found");
            }

            using (var workingDirectory = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, RepositoryInitHelper.ConfigurationBranchName.ToString()))
            {
                var syncFoldersPath = Path.Combine(workingDirectory.Location, s_SyncFolders);
                
                var filePath = Path.Combine(syncFoldersPath, $"{folder.Name}.{s_Json}");
                using (var stream = NativeFile.Open(filePath, FileMode.Open, FileAccess.Write))
                {
                    folder.WriteTo(stream);
                }

                if (workingDirectory.HasChanges)
                {
                    try
                    {
                        workingDirectory.Commit($"Updated SyncFolder '{folder.Name}'");
                        workingDirectory.Push();
                    }
                    catch (EmptyCommitException)
                    {
                        // no changes after all (HasChanges does not seem to be a 100% accurate)
                        // => ignore exception
                    }

                    
                }

            }
        }
示例#10
0
        public void AddItem(ISyncPoint state)
        {
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }
            
            if (ItemExists(state.Id))
            {
                throw new DuplicateSyncPointException(state.Id);
            }

            // create synchronization state branch if necessary
            EnsureBranchExists();

            var directory = new Directory(null, s_DirectoryName)
            {
                d => new SyncPointStateFile(d, state)
            };

            using (var workingDirectory = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, BranchName.ToString()))
            {
                var localItemCreator = new LocalItemCreator();
                localItemCreator.CreateDirectory(directory, workingDirectory.Location);

                workingDirectory.Commit($"{nameof(GitSyncPointService)}: Added SyncPoint {state.Id}");
                workingDirectory.Push();
            }            
        }
        public void GetChangedFiles_ignores_Changes_outside_of_the_Snapshot_directory()
        {
            //ARRANGE
            var state1 = new Directory(s_Dir1);
            var state2 = new Directory(s_Dir1)
            {
                dir1 => new EmptyFile(dir1, "file1")
            };

            var snapshot1 = m_Instance.CreateSnapshot(state1);

            // create unrelated change between two snapshots
            using (var workingDirectory = new TemporaryWorkingDirectory(m_Repository.Info.Path, m_Instance.Id))
            {
                NativeFile.WriteAllText(Path.Combine(workingDirectory.Location, "foo"), "Hello World");
                workingDirectory.Commit();
                workingDirectory.Push();
            }

            var snapshot2 = m_Instance.CreateSnapshot(state2);

            Assert.NotEqual(snapshot1.Id, snapshot2.Id);

            //ACT
            var changedFiles = m_Instance.GetChangedFiles(snapshot1.Id, snapshot2.Id);

            //ASSERT
            Assert.Single(changedFiles);
        }
示例#12
0
        public void AddItems(IEnumerable<ConflictInfo> conflicts)
        {
            if (conflicts == null)
            {
                throw new ArgumentNullException(nameof(conflicts));
            }
            conflicts = conflicts.ToArray();

            if(!conflicts.Any())
            {
                return;
            }

            EnsureBranchExists();

            var exisitngRoot = new GitDirectory(null, "root", GitGroup.Repository.GetLocalBranch(BranchName).Tip);
            var createdRoot = new Directory(null, "root");

            // verify conflicts
            foreach (var conflict in conflicts)
            {                
                var relativePath = GetRelativeConflictInfoFilePath(conflict.FilePath);
                if (exisitngRoot.FileExists(relativePath))
                {
                    throw new DuplicateItemException($"A ConflictInfo for '{conflict.FilePath}' already exists");
                }

                var directory = DirectoryHelper.GetOrAddDirectory(createdRoot, PathParser.GetDirectoryName(relativePath));
                directory.Add(f => new ConflictInfoFile(f, conflict));
            }


            using (var workingDirectory = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, BranchName.ToString()))
            {                
                var localItemCreator = new LocalItemCreator();
                localItemCreator.CreateDirectoryInPlace(createdRoot, workingDirectory.Location);

                workingDirectory.Commit($"{nameof(GitConflictService)}: Added {conflicts.Count()} items");
                workingDirectory.Push();
            }            

        }
示例#13
0
        public void RemoveItems(IEnumerable<ConflictInfo> conflicts)
        {
            if (conflicts == null)
            {
                throw new ArgumentNullException(nameof(conflicts));
            }

            conflicts = conflicts.ToArray();

            if (!conflicts.Any())
            {
                return;
            }

            if (!GitGroup.Repository.LocalBranchExists(BranchName))
            {
                throw new ItemNotFoundException($"There is no ConflictInfo for file '{conflicts.First().FilePath}'");
            }


            var root = new GitDirectory(null, "root", GitGroup.Repository.GetLocalBranch(BranchName).Tip);

            // verify conflicts
            foreach (var conflict in conflicts)
            {             
                var relativePath = GetRelativeConflictInfoFilePath(conflict.FilePath);
                if (!root.FileExists(relativePath))
                {
                    throw new ItemNotFoundException($"There is no ConflictInfo for file '{conflict.FilePath}'");
                }
            }


            // delete conflict info files
            using (var workingDirectory = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, BranchName.ToString()))
            {
                var localDirectory= new LocalDirectory(null, workingDirectory.Location);

                foreach (var conflict in conflicts)
                {
                    var relativePath = GetRelativeConflictInfoFilePath(conflict.FilePath);
                    System.IO.File.Delete(((ILocalFile)localDirectory.GetFile(relativePath)).Location);
                }

                workingDirectory.Commit($"{nameof(GitConflictService)}: Removed {conflicts.Count()} items");
                workingDirectory.Push();
            }                
        }
        public void AddItem(SyncFolder folder)
        {
            if (this.Items.Any(f => f.Name.Equals(folder.Name, StringComparison.CurrentCultureIgnoreCase)))
            {
                throw new DuplicateSyncFolderException(folder.Name);
            }            

            // add config file for the sync folder to the configuration directory
            using (var workingDirectory = new TemporaryWorkingDirectory(GitGroup.Repository.Info.Path, RepositoryInitHelper.ConfigurationBranchName.ToString()))
            {
                var syncFoldersPath = Path.Combine(workingDirectory.Location, s_SyncFolders);

                if (NativeDirectory.Exists(syncFoldersPath) == false)
                {
                    NativeDirectory.CreateDirectory(syncFoldersPath);
                }

                var filePath = Path.Combine(syncFoldersPath, $"{folder.Name}.{s_Json}");
                using (var stream = NativeFile.Open(filePath, FileMode.CreateNew, FileAccess.Write))
                {
                    folder.WriteTo(stream);
                }

                workingDirectory.Commit($"Added SyncFolder '{folder.Name}'");
                workingDirectory.Push();
            }
            
        }
        public void Push_transfers_changes_to_master_directory()
        {
            var fileName = Path.GetRandomFileName();
            using (var instance = new TemporaryWorkingDirectory(m_BareMasterRepository.Directory.Location, "master"))
            {
                CreateFile(instance, fileName);

                instance.Commit();
                instance.Push();
            }
            
            // clone repo again to check if the file we created shows up in new clone
            using (var workingDirectory = new TemporaryWorkingDirectory(m_BareMasterRepository.Directory.Location, "master"))
            {
                Assert.True(IOFile.Exists(Path.Combine(workingDirectory.Location, fileName)));
            }
        }
        public static GitBasedMultiFileSystemSnapshot Create(Repository repository, BranchName branchName, IHistoryService historyService)
        {
            var directoryCreator = new LocalItemCreator();            

            var branch = repository.GetBranch(branchName);

            string commitId;
            using (var workingRepository = new TemporaryWorkingDirectory(repository.Info.Path, branch.FriendlyName))
            {

                var snapshotDirectory = new Directory(null, s_SnapshotDirectoryName);
                foreach (var fileSystemHistory in historyService.Items)
                {
                    var fileName = fileSystemHistory.Name + s_FileNameSuffix;
                    var content = fileSystemHistory.LatestFileSystemSnapshot?.Id ?? "";
                    snapshotDirectory.Add(d => new TextFile(d, fileName, content));
                }
                
                var snapshotDirectoryPath = Path.Combine(workingRepository.Location, s_SnapshotDirectoryName);
                directoryCreator.CreateDirectoryInPlace(snapshotDirectory, snapshotDirectoryPath, true);

                if (workingRepository.HasChanges)
                {
                    try
                    {
                        commitId = workingRepository.Commit("Created multi-filesystem snapshot");
                        workingRepository.Push();
                    }
                    catch (EmptyCommitException)
                    {
                        // no changes after all (HasChanges does not seem to be a 100% accurate)
                        commitId = repository.GetBranch(branchName).Tip.Sha;
                    }

                }
                else
                {
                    commitId = repository.GetBranch(branchName).Tip.Sha;
                }
            }

            var commit = repository.Lookup<Commit>(commitId);
            return IsSnapshot(commit) ? new GitBasedMultiFileSystemSnapshot(commit, historyService) : null;
        }
        public void HasChanges_Returns_True_if_a_file_was_modified()
        {
            using (var instance = new TemporaryWorkingDirectory(m_MasterRepository.Directory.Location, "master"))
            {
                var filePath = Path.Combine(instance.Location, s_File1);
                IOFile.WriteAllText(filePath, "Hello_World");

                Assert.True(instance.HasChanges);

                instance.Commit();

                Assert.False(instance.HasChanges);
                IOFile.WriteAllText(filePath, "Hello World");

                Assert.True(instance.HasChanges);                
            }
        }
        /// <summary>
        /// Adds the specified file to the specified branch using the path of the transaction's local repository
        /// </summary>
        protected void AddFile(IGitTransaction transaction, string branchName, string fileName)
        {
            using (var workingDirectory = new TemporaryWorkingDirectory(transaction.LocalPath, branchName))
            {
                var path = Path.Combine(workingDirectory.Location, fileName);
                File.WriteAllText(path, "Some file content");

                workingDirectory.Commit();
                workingDirectory.Push();                
            }
        }