@ -59,12 +59,14 @@ import java.util.Objects;
import java.util.StringJoiner ;
import java.util.TreeMap ;
import org.eclipse.jgit.annotations.NonNull ;
import org.eclipse.jgit.annotations.Nullable ;
import org.eclipse.jgit.api.Git ;
import org.eclipse.jgit.api.GitCommand ;
import org.eclipse.jgit.api.SubmoduleAddCommand ;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException ;
import org.eclipse.jgit.api.errors.GitAPIException ;
import org.eclipse.jgit.api.errors.InvalidRefNameException ;
import org.eclipse.jgit.api.errors.JGitInternalException ;
import org.eclipse.jgit.dircache.DirCache ;
import org.eclipse.jgit.dircache.DirCacheBuilder ;
@ -80,7 +82,6 @@ import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode ;
import org.eclipse.jgit.lib.ObjectId ;
import org.eclipse.jgit.lib.ObjectInserter ;
import org.eclipse.jgit.lib.ObjectReader ;
import org.eclipse.jgit.lib.PersonIdent ;
import org.eclipse.jgit.lib.ProgressMonitor ;
import org.eclipse.jgit.lib.Ref ;
@ -90,6 +91,7 @@ import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository ;
import org.eclipse.jgit.revwalk.RevCommit ;
import org.eclipse.jgit.revwalk.RevWalk ;
import org.eclipse.jgit.treewalk.TreeWalk ;
import org.eclipse.jgit.util.FileUtils ;
/ * *
@ -144,7 +146,9 @@ public class RepoCommand extends GitCommand<RevCommit> {
* @param uri
* The URI of the remote repository
* @param ref
* The ref ( branch / tag / etc . ) to read
* Name of the ref to lookup . May be a short - hand form , e . g .
* "master" which is is automatically expanded to
* "refs/heads/master" if "refs/heads/master" already exists .
* @return the sha1 of the remote repository , or null if the ref does
* not exist .
* @throws GitAPIException
@ -165,13 +169,93 @@ public class RepoCommand extends GitCommand<RevCommit> {
* @throws GitAPIException
* @throws IOException
* @since 3 . 5
*
* @deprecated Use { @link # readFileWithMode ( String , String , String ) }
* instead
* /
public byte [ ] readFile ( String uri , String ref , String path )
@Deprecated
public default byte [ ] readFile ( String uri , String ref , String path )
throws GitAPIException , IOException {
return readFileWithMode ( uri , ref , path ) . getContents ( ) ;
}
/ * *
* Read contents and mode ( i . e . permissions ) of the file from a remote
* repository .
*
* @param uri
* The URI of the remote repository
* @param ref
* Name of the ref to lookup . May be a short - hand form , e . g .
* "master" which is is automatically expanded to
* "refs/heads/master" if "refs/heads/master" already exists .
* @param path
* The relative path ( inside the repo ) to the file to read
* @return The contents and file mode of the file in the given
* repository and branch . Never null .
* @throws GitAPIException
* If the ref have an invalid or ambiguous name , or it does
* not exist in the repository ,
* @throws IOException
* If the object does not exist or is too large
* @since 5 . 2
* /
@NonNull
public RemoteFile readFileWithMode ( String uri , String ref , String path )
throws GitAPIException , IOException ;
}
/ * *
* Read - only view of contents and file mode ( i . e . permissions ) for a file in
* a remote repository .
*
* @since 5 . 2
* /
public static final class RemoteFile {
@NonNull
private final byte [ ] contents ;
@NonNull
private final FileMode fileMode ;
/ * *
* @param contents
* Raw contents of the file .
* @param fileMode
* Git file mode for this file ( e . g . executable or regular )
* /
public RemoteFile ( @NonNull byte [ ] contents ,
@NonNull FileMode fileMode ) {
this . contents = Objects . requireNonNull ( contents ) ;
this . fileMode = Objects . requireNonNull ( fileMode ) ;
}
/ * *
* Contents of the file .
* < p >
* Callers who receive this reference must not modify its contents ( as
* it can point to internal cached data ) .
*
* @return Raw contents of the file . Do not modify it .
* /
@NonNull
public byte [ ] getContents ( ) {
return contents ;
}
/ * *
* @return Git file mode for this file ( e . g . executable or regular )
* /
@NonNull
public FileMode getFileMode ( ) {
return fileMode ;
}
}
/** A default implementation of {@link RemoteReader} callback. */
public static class DefaultRemoteReader implements RemoteReader {
@Override
public ObjectId sha1 ( String uri , String ref ) throws GitAPIException {
Map < String , Ref > map = Git
@ -183,38 +267,30 @@ public class RepoCommand extends GitCommand<RevCommit> {
}
@Override
public byte [ ] readFil e( String uri , String ref , String path )
public RemoteFile readFileWithMod e( String uri , String ref , String path )
throws GitAPIException , IOException {
File dir = FileUtils . createTempDir ( "jgit_" , ".git" , null ) ; //$NON-NLS-1$ //$NON-NLS-2$
try ( Git git = Git . cloneRepository ( ) . setBare ( true ) . setDirectory ( dir )
. setURI ( uri ) . call ( ) ) {
return readFileFromRepo ( git . getRepository ( ) , ref , path ) ;
Repository repo = git . getRepository ( ) ;
ObjectId refCommitId = sha1 ( uri , ref ) ;
if ( refCommitId = = null ) {
throw new InvalidRefNameException ( MessageFormat
. format ( JGitText . get ( ) . refNotResolved , ref ) ) ;
}
RevCommit commit = repo . parseCommit ( refCommitId ) ;
TreeWalk tw = TreeWalk . forPath ( repo , path , commit . getTree ( ) ) ;
// TODO(ifrade): Cope better with big files (e.g. using
// InputStream instead of byte[])
return new RemoteFile (
tw . getObjectReader ( ) . open ( tw . getObjectId ( 0 ) )
. getCachedBytes ( Integer . MAX_VALUE ) ,
tw . getFileMode ( 0 ) ) ;
} finally {
FileUtils . delete ( dir , FileUtils . RECURSIVE ) ;
}
}
/ * *
* Read a file from the repository
*
* @param repo
* The repository containing the file
* @param ref
* The ref ( branch / tag / etc . ) to read
* @param path
* The relative path ( inside the repo ) to the file to read
* @return the file ' s content
* @throws GitAPIException
* @throws IOException
* @since 3 . 5
* /
protected byte [ ] readFileFromRepo ( Repository repo ,
String ref , String path ) throws GitAPIException , IOException {
try ( ObjectReader reader = repo . newObjectReader ( ) ) {
ObjectId oid = repo . resolve ( ref + ":" + path ) ; //$NON-NLS-1$
return reader . open ( oid ) . getBytes ( Integer . MAX_VALUE ) ;
}
}
}
@SuppressWarnings ( "serial" )