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.
Наследование: 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
        /// <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
 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
 public override void unlock()
 {
     if (_lock != null)
     {
         _lock.Unlock();
         _lock = null;
     }
 }
Пример #5
0
 public LockFileOutputStream(LockFile lockfile)
 {
     _lockFile = lockfile;
 }
Пример #6
0
        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
 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
 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
 public override RefUpdateResult Store(LockFile lockFile, RefUpdateResult status)
 {
     return RefUpdate.UpdateRepositoryStore(lockFile, status);
 }
Пример #10
0
 public abstract RefUpdateResult Store(LockFile lockFile, RefUpdateResult status);
Пример #11
0
            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
        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
        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
 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
        }

        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);
                }