예제 #1
0
        public void RecoverAll()
        {
            var waitingReceivePacks = new List <ParsedReceivePack>();

            foreach (var packDir in recoveryFilePathBuilder.GetPathToPackDirectory())
            {
                foreach (var packFilePath in Directory.GetFiles(packDir))
                {
                    using (var fileReader = new StreamReader(packFilePath))
                    {
                        var packFileData = fileReader.ReadToEnd();
                        waitingReceivePacks.Add(JsonConvert.DeserializeObject <ParsedReceivePack>(packFileData));
                    }
                }
            }

            foreach (var pack in waitingReceivePacks.OrderBy(p => p.Timestamp))
            {
                // execute if the pack has been waiting for X amount of time
                if ((DateTime.Now - pack.Timestamp) >= failedPackWaitTimeBeforeExecution)
                {
                    // re-parse result file and execute "post" hooks
                    // if result file is no longer there then move on
                    var failedPackResultFilePath = recoveryFilePathBuilder.GetPathToResultFile(pack.PackId, pack.RepositoryName, "receive-pack");
                    if (File.Exists(failedPackResultFilePath))
                    {
                        using (var resultFileStream = File.OpenRead(failedPackResultFilePath))
                        {
                            var failedPackResult = resultFileParser.ParseResult(resultFileStream);
                            ProcessOnePack(pack, failedPackResult);
                        }
                        File.Delete(failedPackResultFilePath);
                    }
                }
            }
        }
예제 #2
0
        public void ExecuteServiceByName(string correlationId, string repositoryName, string serviceName, ExecutionOptions options, System.IO.Stream inStream, System.IO.Stream outStream)
        {
            ParsedReceivePack receivedPack = null;

            if (serviceName == "receive-pack" && inStream.Length > 0)
            {
                // PARSING RECEIVE-PACK THAT IS OF THE FOLLOWING FORMAT:
                // (NEW LINES added for ease of reading)
                // (LLLL is length of the line (expressed in HEX) until next LLLL value)
                //
                // LLLL------ REF LINE -----------\0------- OHTER DATA -----------
                // LLLL------ REF LINE ----------------
                // ...
                // ...
                // 0000PACK------- REST OF PACKAGE --------
                //

                var pktLines = new List <ReceivePackPktLine>();

                var buff1   = new byte[1];
                var buff4   = new byte[4];
                var buff20  = new byte[20];
                var buff16K = new byte[1024 * 16];

                while (true)
                {
                    ReadStream(inStream, buff4);
                    var len = Convert.ToInt32(Encoding.UTF8.GetString(buff4), 16);
                    if (len == 0)
                    {
                        break;
                    }
                    len = len - buff4.Length;

                    var accum = new LinkedList <byte>();

                    while (len > 0)
                    {
                        len -= 1;
                        ReadStream(inStream, buff1);
                        if (buff1[0] == 0)
                        {
                            break;
                        }
                        accum.AddLast(buff1[0]);
                    }
                    if (len > 0)
                    {
                        inStream.Seek(len, SeekOrigin.Current);
                    }
                    var pktLine      = Encoding.UTF8.GetString(accum.ToArray());
                    var pktLineItems = pktLine.Split(' ');

                    var fromCommit = pktLineItems[0];
                    var toCommit   = pktLineItems[1];
                    var refName    = pktLineItems[2];

                    pktLines.Add(new ReceivePackPktLine(fromCommit, toCommit, refName));
                }

                // parse PACK contents
                var packCommits = new List <ReceivePackCommit>();

                // PACK format
                // https://www.kernel.org/pub/software/scm/git/docs/technical/pack-format.html
                // http://schacon.github.io/gitbook/7_the_packfile.html

                if (inStream.Position < inStream.Length)
                {
                    ReadStream(inStream, buff4);
                    if (Encoding.UTF8.GetString(buff4) != "PACK")
                    {
                        throw new Exception("Unexpected receive-pack 'PACK' content.");
                    }
                    ReadStream(inStream, buff4);
                    Array.Reverse(buff4);
                    var versionNum = BitConverter.ToInt32(buff4, 0);

                    ReadStream(inStream, buff4);
                    Array.Reverse(buff4);
                    var numObjects = BitConverter.ToInt32(buff4, 0);

                    while (numObjects > 0)
                    {
                        numObjects -= 1;

                        ReadStream(inStream, buff1);
                        var  type = (GIT_OBJ_TYPE)((buff1[0] >> 4) & 7);
                        long len  = buff1[0] & 15;

                        var shiftAmount = 4;
                        while ((buff1[0] >> 7) == 1)
                        {
                            ReadStream(inStream, buff1);
                            len = len | ((long)(buff1[0] & 127) << shiftAmount);

                            shiftAmount += 7;
                        }

                        if (type == GIT_OBJ_TYPE.OBJ_REF_DELTA)
                        {
                            // read ref name
                            ReadStream(inStream, buff20);
                        }
                        if (type == GIT_OBJ_TYPE.OBJ_OFS_DELTA)
                        {
                            // read negative offset
                            ReadStream(inStream, buff1);
                            while ((buff1[0] >> 7) == 1)
                            {
                                ReadStream(inStream, buff1);
                            }
                        }

                        var  origPosition = inStream.Position;
                        long offsetVal    = 0;

                        using (var zlibStream = new ZlibStream(inStream, CompressionMode.Decompress, true))
                        {
                            // read compressed data max 16KB at a time
                            var readRemaining = len;
                            do
                            {
                                var bytesUncompressed = zlibStream.Read(buff16K, 0, buff16K.Length);
                                readRemaining -= bytesUncompressed;
                            } while (readRemaining > 0);

                            if (type == GIT_OBJ_TYPE.OBJ_COMMIT)
                            {
                                var parsedCommit = ParseCommitDetails(buff16K, len);
                                packCommits.Add(parsedCommit);
                            }
                            offsetVal = zlibStream.TotalIn;
                        }
                        // move back position a bit because ZLibStream reads more than needed for inflating
                        inStream.Seek(origPosition + offsetVal, SeekOrigin.Begin);
                    }
                }
                // -------------------

                var user = HttpContext.Current.User.Username();
                receivedPack = new ParsedReceivePack(correlationId, repositoryName, pktLines, user, DateTime.Now, packCommits);

                inStream.Seek(0, SeekOrigin.Begin);

                receivePackHandler.PrePackReceive(receivedPack);
            }

            GitExecutionResult execResult = null;

            using (var capturedOutputStream = new MemoryStream())
            {
                gitService.ExecuteServiceByName(correlationId, repositoryName, serviceName, options, inStream, new ReplicatingStream(outStream, capturedOutputStream));

                // parse captured output
                capturedOutputStream.Seek(0, SeekOrigin.Begin);
                execResult = resultParser.ParseResult(capturedOutputStream);
            }

            if (receivedPack != null)
            {
                receivePackHandler.PostPackReceive(receivedPack, execResult);
            }
        }