-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add `InfoRefs` slice implementation which returns server metadata and supported command that server can handle. Based on this response git client decide what command to execute next. Add `GitResponseOutput` to format ASCI text as git response with length prefixes and part-end symbols. Add `main` entry point to debug Artipie git server on localhost. Update integration test `GitITCase`: setup bare repo on storage, updated `ls-remote` test, added correct assertiion for `ls-remote` test. Ticket: #1 Ticket: #11
- Loading branch information
Showing
10 changed files
with
450 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,14 +27,26 @@ SOFTWARE. | |
<parent> | ||
<groupId>com.artipie</groupId> | ||
<artifactId>ppom</artifactId> | ||
<version>1.0.4</version> | ||
<version>1.1.0</version> | ||
</parent> | ||
<artifactId>git-adapter</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<name>git-adapter</name> | ||
<description>An Artipie adapter for git repositories</description> | ||
<url>https://github.com/artipie/git-adapter</url> | ||
<inceptionYear>2021</inceptionYear> | ||
<developers> | ||
<developer> | ||
<id>g4s8</id> | ||
<name>Kirill Che.</name> | ||
<email>[email protected]</email> | ||
<organization>Artipie</organization> | ||
<organizationUrl>https://www.artipie.com</organizationUrl> | ||
<roles> | ||
<role>maintainer</role> | ||
</roles> | ||
</developer> | ||
</developers> | ||
<licenses> | ||
<license> | ||
<name>MIT</name> | ||
|
@@ -92,7 +104,6 @@ SOFTWARE. | |
<groupId>com.artipie</groupId> | ||
<artifactId>vertx-server</artifactId> | ||
<version>0.5</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.testcontainers</groupId> | ||
|
@@ -103,83 +114,29 @@ SOFTWARE. | |
<dependency> | ||
<groupId>log4j</groupId> | ||
<artifactId>log4j</artifactId> | ||
<scope>test</scope> | ||
<!-- <scope>test</scope> --> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-log4j12</artifactId> | ||
<scope>test</scope> | ||
<!-- <scope>test</scope> --> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
<version>1.8.0-alpha2</version> | ||
<scope>test</scope> | ||
<!-- <scope>test</scope> --> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.junit.jupiter</groupId> | ||
<artifactId>junit-jupiter-params</artifactId> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>commons-io</groupId> | ||
<artifactId>commons-io</artifactId> | ||
<version>2.11.0</version> | ||
<scope>test</scope> | ||
</dependency> | ||
</dependencies> | ||
<build> | ||
<pluginManagement> | ||
<plugins> | ||
<plugin> | ||
<artifactId>maven-surefire-plugin</artifactId> | ||
<version>3.0.0-M5</version> | ||
<configuration combine.children="overwrite"> | ||
<failIfNoTests>false</failIfNoTests> | ||
<failIfNoSpecifiedTests>false</failIfNoSpecifiedTests> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</pluginManagement> | ||
<plugins> | ||
<plugin> | ||
<groupId>com.jcabi</groupId> | ||
<artifactId>jcabi-maven-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<id>jcabi-versionalize-packages</id> | ||
<phase>none</phase> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
<plugin> | ||
<artifactId>maven-failsafe-plugin</artifactId> | ||
<executions> | ||
<execution> | ||
<goals> | ||
<goal>integration-test</goal> | ||
<goal>verify</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
<profiles> | ||
<profile> | ||
<id>qulice</id> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>com.qulice</groupId> | ||
<artifactId>qulice-maven-plugin</artifactId> | ||
<version>0.19.4</version> | ||
<configuration> | ||
<excludes combine.children="append"> | ||
<exclude>findbugs:.*</exclude> | ||
<exclude>duplicatefinder:.*</exclude> | ||
<exclude>xml:/src/it/settings.xml</exclude> | ||
<exclude>dependencies:.*</exclude> | ||
<exclude>checkstyle:.*/src/test/resources/.*</exclude> | ||
</excludes> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</profile> | ||
</profiles> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/* | ||
* The MIT License (MIT) Copyright (c) 2020-2021 artipie.com | ||
* https://github.com/artipie/git-adapter/LICENSE.txt | ||
*/ | ||
package com.artipie.git; | ||
|
||
import java.io.IOException; | ||
import java.io.Writer; | ||
|
||
/** | ||
* Git response formatter writes binary data to | ||
* wrapped {@link Writer} with correct identations and | ||
* line prefixes. | ||
* <p> | ||
* Git response data consists of any number of part, each part | ||
* ends with empty line (no data binary line).<br/> | ||
* Git data line contains ASCI characters.<br/> | ||
* Each data line is prefixed with 4-byte length of full line in hex ASCI | ||
* format, e.g. text hello will be printed as | ||
* {@code `000ahello\n`: `000a = hex(4 + len("hello") + 1)}<br/> | ||
* Each part ends with empty data line: {@code 0000}. | ||
* @since 1.0 | ||
*/ | ||
final class GitResponseOutput { | ||
|
||
/** | ||
* End part symbols. | ||
*/ | ||
private static final char[] END_PART = new char[]{'0', '0', '0', '0'}; | ||
|
||
/** | ||
* Output writer. | ||
*/ | ||
private final Writer out; | ||
|
||
/** | ||
* New git output. | ||
* @param writer Writer | ||
*/ | ||
GitResponseOutput(final Writer writer) { | ||
this.out = writer; | ||
} | ||
|
||
/** | ||
* Push new line to output, format it as git data line. | ||
* @param line ASCI text line | ||
* @throws IOException On IO error | ||
* @checkstyle MagicNumberCheck (10 lines) | ||
*/ | ||
void pushLine(final String line) throws IOException { | ||
final char[] src = line.toCharArray(); | ||
final char[] res = new char[src.length + 5]; | ||
final char[] len = String.format("%04x", res.length).toCharArray(); | ||
System.arraycopy(len, 0, res, 0, len.length); | ||
System.arraycopy(src, 0, res, len.length, src.length); | ||
res[res.length - 1] = '\n'; | ||
this.out.write(res); | ||
} | ||
|
||
/** | ||
* Write end part symbol. | ||
* @throws IOException Of IO error | ||
*/ | ||
void endPart() throws IOException { | ||
this.out.write(GitResponseOutput.END_PART); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/* | ||
* The MIT License (MIT) Copyright (c) 2020-2021 artipie.com | ||
* https://github.com/artipie/git-adapter/LICENSE.txt | ||
*/ | ||
package com.artipie.git; | ||
|
||
import com.artipie.asto.ArtipieIOException; | ||
import com.artipie.asto.Content; | ||
import com.artipie.http.ArtipieHttpException; | ||
import com.artipie.http.Response; | ||
import com.artipie.http.Slice; | ||
import com.artipie.http.headers.ContentType; | ||
import com.artipie.http.rq.RequestLineFrom; | ||
import com.artipie.http.rq.RqParams; | ||
import com.artipie.http.rs.RsStatus; | ||
import com.artipie.http.rs.RsWithBody; | ||
import com.artipie.http.rs.RsWithHeaders; | ||
import com.artipie.http.rs.StandardRs; | ||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.io.OutputStreamWriter; | ||
import java.nio.ByteBuffer; | ||
import java.util.Map.Entry; | ||
import java.util.Set; | ||
import org.reactivestreams.Publisher; | ||
|
||
/** | ||
* Slice to handle {@code /info/refs} - it's used | ||
* to send metadata about git server, it shows supported commands | ||
* services, versions, etc. | ||
* @since 1.0 | ||
* @checkstyle ClassDataAbstractionCouplingCheck (500 lines) | ||
* @checkstyle MethodBodyCommentsCheck (500 lines) | ||
*/ | ||
final class InfoRefsSlice implements Slice { | ||
|
||
/** | ||
* Server agent name. | ||
*/ | ||
private final String agent; | ||
|
||
/** | ||
* Supported commands. | ||
*/ | ||
private final Set<String> commands; | ||
|
||
/** | ||
* New slice. | ||
* @param agent Server agent name | ||
* @param commands Supported commands with annotations | ||
*/ | ||
InfoRefsSlice(final String agent, final Set<String> commands) { | ||
this.agent = agent; | ||
this.commands = commands; | ||
} | ||
|
||
@Override | ||
public Response response(final String line, final Iterable<Entry<String, String>> headers, | ||
final Publisher<ByteBuffer> body) { | ||
final String service = new RqParams(new RequestLineFrom(line).uri()).value("service") | ||
.orElseThrow( | ||
() -> new ArtipieHttpException( | ||
RsStatus.BAD_REQUEST, | ||
"service query param required" | ||
) | ||
); | ||
// this response is very small: <1K - it doesn't consume a lot of memory | ||
// and it could be constructed in byte-array right here | ||
final ByteArrayOutputStream baos = new ByteArrayOutputStream(256); | ||
try (OutputStreamWriter osw = new OutputStreamWriter(baos)) { | ||
final GitResponseOutput gwr = new GitResponseOutput(osw); | ||
gwr.pushLine(String.format("# service=%s", service)); | ||
gwr.endPart(); | ||
gwr.pushLine("version 2"); | ||
gwr.pushLine(String.format("agent=%s", this.agent)); | ||
for (final String cmd : this.commands) { | ||
gwr.pushLine(cmd); | ||
} | ||
gwr.pushLine("server-option"); | ||
gwr.pushLine("object-format=sha1"); | ||
gwr.endPart(); | ||
} catch (final IOException iex) { | ||
throw new ArtipieHttpException(RsStatus.INTERNAL_ERROR, new ArtipieIOException(iex)); | ||
} | ||
return new RsWithBody( | ||
new RsWithHeaders( | ||
StandardRs.OK, | ||
new ContentType("application/x-git-upload-pack-advertisement") | ||
), | ||
new Content.From(baos.toByteArray()) | ||
); | ||
} | ||
} |
Oops, something went wrong.