All Downloads are FREE. Search and download functionalities are using the official Maven repository.

br.com.objectos.git.OpenPackFile Maven / Gradle / Ivy

Go to download

ObjectosGit is a pure Java library that provides a limited set of GIT operations.

The newest version!
/*
 * Copyright (C) 2020-2022 Objectos Software LTDA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package br.com.objectos.git;

import br.com.objectos.core.io.Charsets;
import br.com.objectos.core.object.Checks;
import br.com.objectos.core.throwable.Try;
import br.com.objectos.fs.Directory;
import br.com.objectos.fs.NotRegularFileException;
import br.com.objectos.fs.PathNameVisitor;
import br.com.objectos.fs.ReadableFileChannelSource;
import br.com.objectos.fs.RegularFile;
import br.com.objectos.fs.ResolvedPath;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Opens a Git packfile. Resolves the pathname and confirms (or not) that the
 * file exist. Validates the header and (maybe) the checksum. Opens the
 * associated index file (if one exists).
 *
 * 

* Apart from validating the header and (maybe) the checksum, does not do any * further reading. * * @since 3 */ final class OpenPackFile extends AbstractGitEngineTask { private static final byte _IDX_HEADER = 2; private static final byte _PACK_HEADER = 3; private static final int IDX_LENGTH = 4 + 4; private static final byte IO_IDX = 1; private static final byte IO_PACK = 2; private static final int PACK_IDX2_MAGIC = 0xff744f63; private static final int PACK_LENGTH = 4 + 4 + 4; private static final byte[] PACK_SIGNATURE = "PACK".getBytes(Charsets.usAscii()); private ByteBuffer channelBuffer; private RegularFile indexFile; private int objectCount; private ObjectId objectId; private RegularFile packFile; private long packFileSize; private Directory repository; private int version; OpenPackFile(GitInjector injector) { super(injector); } public final void set(Directory objectsDirectory, ObjectId objectId) { checkSetInput(); this.repository = Checks.checkNotNull(objectsDirectory, "objectsDirectory == null"); this.objectId = Checks.checkNotNull(objectId, "objectId == null"); } @Override final byte execute(byte state) { switch (state) { case _IDX_HEADER: return executeIdxHeader(); case _PACK_HEADER: return executePackHeader(); default: return super.execute(state); } } @Override final byte executeFinally() { channelBuffer = injector.putByteBuffer(channelBuffer); indexFile = null; objectCount = 0; objectId = null; packFile = null; packFileSize = 0; repository = null; version = 0; return super.executeFinally(); } @Override final void executeIo(byte task) throws GitStubException, IOException { switch (task) { case IO_IDX: ioIdx(); break; case IO_PACK: ioPack(); break; default: super.executeIo(task); break; } } @Override final byte executeStart() { super.executeStart(); channelBuffer = injector.getByteBuffer(); channelBuffer.clear(); channelBuffer.limit(PACK_LENGTH); return toIo(IO_PACK, _PACK_HEADER, _FINALLY); } final void openIdx(RegularFile file) throws IOException { indexFile = file; ioRead(indexFile); } private byte executeIdxHeader() { int magic; magic = channelBuffer.getInt(); if (magic != PACK_IDX2_MAGIC) { return toBadObject("Invalid or corrupt index file: " + indexFile.getPath()); } int idxVersion; idxVersion = channelBuffer.getInt(); if (idxVersion != 2) { return toBadObject("Invalid or corrupt index file: " + indexFile.getPath()); } setResult( new IndexedPackFile(indexFile, objectCount, objectId, packFile, packFileSize, version) ); return _FINALLY; } private byte executePackHeader() { if (!Git.matches(channelBuffer, PACK_SIGNATURE)) { return toBadObject("PACK signature not found"); } version = channelBuffer.getInt(); objectCount = channelBuffer.getInt(); channelBuffer.clear(); channelBuffer.limit(IDX_LENGTH); return toIo(IO_IDX, _IDX_HEADER, _FINALLY); } private void ioIdx() throws IOException { String fileName; fileName = objectId.toString("pack-", ".idx"); ResolvedPath maybeIdx; maybeIdx = repository.resolve("pack", fileName); maybeIdx.acceptPathNameVisitor(IoIdx.INSTANCE, this); } private void ioPack() throws IOException { String fileName; fileName = objectId.toString("pack-", ".pack"); ResolvedPath maybePackFile; maybePackFile = repository.resolve("pack", fileName); // fail if not a regular file packFile = maybePackFile.toRegularFile(); packFileSize = packFile.size(); ioRead(packFile); } private void ioRead(ReadableFileChannelSource source) throws IOException { Throwable rethrow; rethrow = Try.begin(); FileChannel channel; channel = source.openReadChannel(); try { channel.position(0); channel.read(channelBuffer); channelBuffer.flip(); } catch (Throwable e) { rethrow = e; } finally { rethrow = Try.close(rethrow, channel); } Try.rethrowIfPossible(rethrow, IOException.class); if (rethrow != null) { catchThrowable(rethrow); } } private byte toBadObject(String message) { return toError( new BadObjectException(objectId, message) ); } private enum IoIdx implements PathNameVisitor { INSTANCE; @Override public final Void visitDirectory(Directory directory, OpenPackFile p) throws IOException { p.catchThrowable( new NotRegularFileException(directory) ); return null; } @Override public final Void visitNotFound(ResolvedPath notFound, OpenPackFile p) throws IOException { p.ioReady(_FINALLY); return null; } @Override public final Void visitRegularFile(RegularFile file, OpenPackFile p) throws IOException { p.openIdx(file); return null; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy