FirstWant.java

  1. /*
  2.  * Copyright (C) 2018, Google LLC. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */
  10. package org.eclipse.jgit.internal.transport.parser;

  11. import static org.eclipse.jgit.transport.GitProtocolConstants.OPTION_AGENT;

  12. import java.util.Collections;
  13. import java.util.HashSet;
  14. import java.util.Set;

  15. import org.eclipse.jgit.annotations.Nullable;
  16. import org.eclipse.jgit.errors.PackProtocolException;
  17. import org.eclipse.jgit.internal.JGitText;

  18. /**
  19.  * In the pack negotiation phase (protocol v0/v1), the client sends a list of
  20.  * wants. The first "want" line is special, as it (can) have a list of
  21.  * capabilities appended.
  22.  *
  23.  * E.g. "want oid cap1 cap2 cap3"
  24.  *
  25.  * Do not confuse this line with the first one in the reference advertisement,
  26.  * which is sent by the server, looks like
  27.  * "b8f7c471373b8583ced0025cfad8c9916c484b76 HEAD\0 cap1 cap2 cap3" and is
  28.  * parsed by the BasePackConnection.readAdvertisedRefs method.
  29.  *
  30.  * This class parses the input want line and holds the results: the actual want
  31.  * line and the capabilities.
  32.  *
  33.  */
  34. public class FirstWant {
  35.     private final String line;

  36.     private final Set<String> capabilities;

  37.     @Nullable
  38.     private final String agent;

  39.     private static final String AGENT_PREFIX = OPTION_AGENT + '=';

  40.     /**
  41.      * Parse the first want line in the protocol v0/v1 pack negotiation.
  42.      *
  43.      * @param line
  44.      *            line from the client.
  45.      * @return an instance of FirstWant
  46.      * @throws PackProtocolException
  47.      *             if the line doesn't follow the protocol format.
  48.      */
  49.     public static FirstWant fromLine(String line) throws PackProtocolException {
  50.         String wantLine;
  51.         Set<String> capabilities;
  52.         String agent = null;

  53.         if (line.length() > 45) {
  54.             String opt = line.substring(45);
  55.             if (!opt.startsWith(" ")) { //$NON-NLS-1$
  56.                 throw new PackProtocolException(JGitText.get().wantNoSpaceWithCapabilities);
  57.             }
  58.             opt = opt.substring(1);

  59.             HashSet<String> opts = new HashSet<>();
  60.             for (String clientCapability : opt.split(" ")) { //$NON-NLS-1$
  61.                 if (clientCapability.startsWith(AGENT_PREFIX)) {
  62.                     agent = clientCapability.substring(AGENT_PREFIX.length());
  63.                 } else {
  64.                     opts.add(clientCapability);
  65.                 }
  66.             }
  67.             wantLine = line.substring(0, 45);
  68.             capabilities = Collections.unmodifiableSet(opts);
  69.         } else {
  70.             wantLine = line;
  71.             capabilities = Collections.emptySet();
  72.         }

  73.         return new FirstWant(wantLine, capabilities, agent);
  74.     }

  75.     private FirstWant(String line, Set<String> capabilities,
  76.             @Nullable String agent) {
  77.         this.line = line;
  78.         this.capabilities = capabilities;
  79.         this.agent = agent;
  80.     }

  81.     /** @return non-capabilities part of the line. */
  82.     public String getLine() {
  83.         return line;
  84.     }

  85.     /**
  86.      * @return capabilities parsed from the line as an immutable set (excluding
  87.      *         agent).
  88.      */
  89.     public Set<String> getCapabilities() {
  90.         return capabilities;
  91.     }

  92.     /** @return client user agent parsed from the line. */
  93.     @Nullable
  94.     public String getAgent() {
  95.         return agent;
  96.     }
  97. }