Git style file locking and replacement. To modify a ref file Git tries to use an atomic update approach: we write the new data into a brand new file, then rename it in place over the old name. This way we can just delete the temporary file if anything goes wrong, and nothing has been damaged. To coordinate access from multiple processes at once Git tries to atomically create the new temporary file under a well-known name.
Inheritance: IDisposable
コード例 #1
0
		protected override void writeFile(string file, byte[] content) {
			FileInfo p = PathUtil.CombineFilePath(_db.Directory, file);
			LockFile lck = new LockFile(p);
			if (!lck.Lock())
				throw new ObjectWritingException("Can't write " + p);
			try {
				lck.Write(content);
			}
			catch (IOException) {
				throw new ObjectWritingException("Can't write " + p);
			}
			if (!lck.Commit())
				throw new ObjectWritingException("Can't write " + p);
		}
コード例 #2
0
ファイル: PackLock.cs プロジェクト: dev218/GitSharp
        /// <summary>
        /// Create the <code>pack-*.keep</code> file, with the given message.
        /// </summary>
        /// <param name="msg">message to store in the file.</param>
        /// <returns>
        /// true if the keep file was successfully written; false otherwise.
        /// </returns>
        /// <exception cref="IOException">
		/// The keep file could not be written.
        /// </exception>
        public bool Lock(string msg)
        {
            if (msg == null) 
				return false;
			
            if (!msg.EndsWith("\n")) msg += "\n";
            using(LockFile lf = new LockFile(_keepFile))
			{
	            if (!lf.Lock()) 
					return false;
	            lf.Write(Constants.encode(msg));
	            return lf.Commit();
			}
        }
コード例 #3
0
ファイル: RefDirectoryUpdate.cs プロジェクト: dev218/GitSharp
 protected override bool tryLock(bool deref)
 {
     Ref dst = Ref;
     if (deref)
         dst = dst.getLeaf();
     string name = dst.getName();
     _lock = new LockFile(_database.fileFor(name));
     if (_lock.Lock())
     {
         dst = _database.getRef(name);
         OldObjectId = (dst != null ? dst.getObjectId() : null);
         return true;
     }
     else
     {
         return false;
     }
 }
コード例 #4
0
ファイル: RefDirectoryUpdate.cs プロジェクト: dev218/GitSharp
 public override void unlock()
 {
     if (_lock != null)
     {
         _lock.Unlock();
         _lock = null;
     }
 }
コード例 #5
0
ファイル: LockFile.cs プロジェクト: jagregory/GitSharp
 public LockFileOutputStream(LockFile lockfile)
 {
     _lockFile = lockfile;
 }
コード例 #6
0
ファイル: RefUpdateTest.cs プロジェクト: georgeck/GitSharp
        public void tryRenameWhenLocked(string toLock, string fromName,
            string toName, string headPointsTo)
        {
            // setup
            db.WriteSymref(Constants.HEAD, headPointsTo);
            ObjectId oldfromId = db.Resolve(fromName);
            ObjectId oldHeadId = db.Resolve(Constants.HEAD);
            RefLogWriter.WriteReflog(db, oldfromId, oldfromId, "Just a message",
                    fromName);
            IList<ReflogReader.Entry> oldFromLog = db
                    .ReflogReader(fromName).getReverseEntries();
            IList<ReflogReader.Entry> oldHeadLog = oldHeadId != null ? db
                    .ReflogReader(Constants.HEAD).getReverseEntries() : null;

            Assert.IsTrue(new FileInfo(Path.Combine(db.Directory.FullName, "logs/" + fromName)).Exists, "internal check, we have a log");

            // "someone" has branch X locked
            var lockFile = new LockFile(new FileInfo(Path.Combine(db.Directory.FullName, toLock)));
            try
            {
                Assert.IsTrue(lockFile.Lock());

                // Now this is our test
                RefRename renameRef = db.RenameRef(fromName, toName);
                RefUpdate.RefUpdateResult result = renameRef.Rename();
                Assert.AreEqual(RefUpdate.RefUpdateResult.LockFailure, result);

                // Check that the involved refs are the same despite the failure
                assertExists(false, toName);
                if (!toLock.Equals(toName))
                    assertExists(false, toName + ".lock");
                assertExists(true, toLock + ".lock");
                if (!toLock.Equals(fromName))
                    assertExists(false, "logs/" + fromName + ".lock");
                assertExists(false, "logs/" + toName + ".lock");
                Assert.AreEqual(oldHeadId, db.Resolve(Constants.HEAD));
                Assert.AreEqual(oldfromId, db.Resolve(fromName));
                Assert.IsNull(db.Resolve(toName));
                Assert.AreEqual(oldFromLog.ToString(), db.ReflogReader(fromName)
                        .getReverseEntries().ToString());
                if (oldHeadId != null)
                    Assert.AreEqual(oldHeadLog, db.ReflogReader(Constants.HEAD)
                            .getReverseEntries());
            }
            finally
            {
                lockFile.Unlock();
            }
        }
コード例 #7
0
ファイル: RefUpdateTest.cs プロジェクト: georgeck/GitSharp
 public void testUpdateRefLockFailureLocked()
 {
     ObjectId opid = db.Resolve("refs/heads/master");
     ObjectId pid = db.Resolve("refs/heads/master^");
     RefUpdate updateRef = db.UpdateRef("refs/heads/master");
     updateRef.NewObjectId = pid;
     var lockFile1 = new LockFile(new FileInfo(Path.Combine(db.Directory.FullName, "refs/heads/master")));
     try
     {
         Assert.IsTrue(lockFile1.Lock()); // precondition to test
         RefUpdate.RefUpdateResult update = updateRef.Update();
         Assert.AreEqual(RefUpdate.RefUpdateResult.LockFailure, update);
         Assert.AreEqual(opid, db.Resolve("refs/heads/master"));
         var lockFile2 = new LockFile(new FileInfo(Path.Combine(db.Directory.FullName, "refs/heads/master")));
         Assert.IsFalse(lockFile2.Lock()); // was locked, still is
     }
     finally
     {
         lockFile1.Unlock();
     }
 }
コード例 #8
0
ファイル: FileBasedConfig.cs プロジェクト: georgeck/GitSharp
 public void save()
 {
     byte[] o = Constants.encode(toText());
     LockFile lf = new LockFile(getFile());
     if (!lf.Lock())
         throw new IOException("Cannot lock " + getFile());
     try
     {
         lf.Write(o);
         if (!lf.Commit())
             throw new IOException("Cannot commit write to " + getFile());
     }
     finally
     {
         lf.Unlock();
     }
 }
コード例 #9
0
ファイル: RefUpdate.cs プロジェクト: stschake/GitSharp
 public override RefUpdateResult Store(LockFile lockFile, RefUpdateResult status)
 {
     return RefUpdate.UpdateRepositoryStore(lockFile, status);
 }
コード例 #10
0
ファイル: RefUpdate.cs プロジェクト: stschake/GitSharp
 public abstract RefUpdateResult Store(LockFile lockFile, RefUpdateResult status);
コード例 #11
0
ファイル: RefUpdate.cs プロジェクト: stschake/GitSharp
            public override RefUpdateResult Store(LockFile @lockFile, RefUpdateResult status)
            {
                var storage = RefUpdate._ref.StorageFormat;
                if (storage == Ref.Storage.New)
                {
                    return status;
                }

                if (storage.IsPacked)
                {
                    RefUpdate._db.RemovePackedRef(RefUpdate._ref.Name);
                }

                int levels = Count(RefUpdate._ref.Name, '/') - 2;

                // Delete logs _before_ unlocking
                DirectoryInfo gitDir = RefUpdate._db.Repository.Directory;
                var logDir = new DirectoryInfo(gitDir + "/" + Constants.LOGS);
                DeleteFileAndEmptyDir(new FileInfo(logDir + "/" + RefUpdate._ref.Name), levels);

                // We have to unlock before (maybe) deleting the parent directories
                lockFile.Unlock();
                if (storage.IsLoose)
                {
                    DeleteFileAndEmptyDir(RefUpdate._looseFile, levels);
                }
                return status;
            }
コード例 #12
0
ファイル: RefUpdate.cs プロジェクト: stschake/GitSharp
        private RefUpdateResult UpdateRepositoryStore(LockFile @lock, RefUpdateResult status)
        {
            if (status == RefUpdateResult.NoChange) return status;

            @lock.NeedStatInformation = true;
            @lock.Write(_newValue);

            string msg = GetRefLogMessage();

            if (msg != null)
            {
                if (_refLogIncludeResult)
                {
                    string strResult = ToResultString(status);
                    if (strResult != null)
                    {
                        msg = !string.IsNullOrEmpty(msg) ? msg + ": " + strResult : strResult;
                    }
                }

                RefLogWriter.append(this, msg);
            }

            if ([email protected]())
            {
                return RefUpdateResult.LockFailure;
            }

            _db.Stored(_ref.OriginalName, _ref.Name, _newValue, @lock.CommitLastModified);
            return status;
        }
コード例 #13
0
ファイル: RefUpdate.cs プロジェクト: stschake/GitSharp
        private RefUpdateResult UpdateImpl(RevWalk.RevWalk walk, StoreBase store)
        {
            if (isNameConflicting())
            {
                return RefUpdateResult.LockFailure;
            }

            using (LockFile @lock = new LockFile(_looseFile))
            {
                if ([email protected]())
                {
                    return RefUpdateResult.LockFailure;
                }

                OldObjectId = _db.IdOf(Name);
                if (_expValue != null)
                {
                    ObjectId o = OldObjectId ?? ObjectId.ZeroId;
                    if (!AnyObjectId.equals(_expValue, o))
                    {
                        return RefUpdateResult.LockFailure;
                    }
                }

                if (OldObjectId == null)
                {
                    return store.Store(@lock, RefUpdateResult.New);
                }

                RevObject newObj = SafeParse(walk, _newValue);
                RevObject oldObj = SafeParse(walk, OldObjectId);
                if (newObj == oldObj)
                {
                    return store.Store(@lock, RefUpdateResult.NoChange);
                }

                RevCommit newCom = (newObj as RevCommit);
                RevCommit oldCom = (oldObj as RevCommit);
                if (newCom != null && oldCom != null)
                {
                    if (walk.isMergedInto(oldCom, newCom))
                    {
                        return store.Store(@lock, RefUpdateResult.FastForward);
                    }
                }

                if (IsForceUpdate)
                {
                    return store.Store(@lock, RefUpdateResult.Forced);
                }

                return RefUpdateResult.Rejected;
            }
        }
コード例 #14
0
ファイル: LockFile.cs プロジェクト: kkl713/GitSharp
 public LockFileOutputStream(LockFile lockfile)
 {
     _lockFile = lockfile;
 }
コード例 #15
0
 private void commitPackedRefs(LockFile lck, RefList <Ref> refs, PackedRefList oldPackedList)
 {
     new PackedRefsWriter(lck, refs, oldPackedList, packedRefs).writePackedRefs();
 }
コード例 #16
0
ファイル: RefDatabase.cs プロジェクト: stschake/GitSharp
        }

        private static void LockAndWriteFile(FileInfo file, byte[] content)
        {
            string name = file.Name;
            using (LockFile lck = new LockFile(file))
            {
                if (!lck.Lock())
                {
                    throw new ObjectWritingException("Unable to lock " + name);
                }

                try
                {
                    lck.Write(content);
                }
                catch (IOException ioe)
                {
                    throw new ObjectWritingException("Unable to write " + name, ioe);
                }
                if (!lck.Commit())
                {
                    throw new ObjectWritingException("Unable to write " + name);
                }