git svn - Checkout remote branch using git svn

ID : 20132

viewed : 34

Tags : gitgit-svngit

Top 5 Answer for git svn - Checkout remote branch using git svn

vote vote

99

Standard Subversion layout

Create a git clone of that includes your Subversion trunk, tags, and branches with

git svn clone http://svn.example.com/project -T trunk -b branches -t tags

The --stdlayout option is a nice shortcut if your Subversion repository uses the typical structure:

git svn clone http://svn.example.com/project --stdlayout

Make your git repository ignore everything the subversion repo does:

git svn show-ignore >> .git/info/exclude

You should now be able to see all the Subversion branches on the git side:

git branch -r

Say the name of the branch in Subversion is waldo. On the git side, you'd run

git checkout -b waldo-svn remotes/waldo

The -svn suffix is to avoid warnings of the form

warning: refname 'waldo' is ambiguous.

To update the git branch waldo-svn, run

git checkout waldo-svn git svn rebase

Starting from a trunk-only checkout

To add a Subversion branch to a trunk-only clone, modify your git repository's .git/config to contain

[svn-remote "svn-mybranch"]         url = http://svn.example.com/project/branches/mybranch         fetch = :refs/remotes/mybranch

You'll need to develop the habit of running

git svn fetch --fetch-all

to update all of what git svn thinks are separate remotes. At this point, you can create and track branches as above. For example, to create a git branch that corresponds to mybranch, run

git checkout -b mybranch-svn remotes/mybranch

For the branches from which you intend to git svn dcommit, keep their histories linear!


Further information

You may also be interested in reading an answer to a related question.

vote vote

84

vote vote

74

TokenAuthenticator depends an a service class. The service class depends on an OkHttpClient instance. To create an OkHttpClient I need the TokenAuthenticator. How can I break this cycle? Two different OkHttpClients? They are going to have different connection pools..

If you have, say, a Retrofit TokenService that you need inside your Authenticator but you would only like to set up one OkHttpClient you can use a TokenServiceHolder as a dependency for TokenAuthenticator. You would have to maintain a reference to it at the application (singleton) level. This is easy if you are using Dagger 2, otherwise just create class field inside your Application.

In TokenAuthenticator.java

public class TokenAuthenticator implements Authenticator {      private final TokenServiceHolder tokenServiceHolder;      public TokenAuthenticator(TokenServiceHolder tokenServiceHolder) {         this.tokenServiceHolder = tokenServiceHolder;     }      @Override     public Request authenticate(Proxy proxy, Response response) throws IOException {          //is there a TokenService?         TokenService service = tokenServiceHolder.get();         if (service == null) {             //there is no way to answer the challenge             //so return null according to Retrofit's convention             return null;         }          // Refresh your access_token using a synchronous api request         newAccessToken = service.refreshToken().execute();          // Add new header to rejected request and retry it         return response.request().newBuilder()                 .header(AUTHORIZATION, newAccessToken)                 .build();     }      @Override     public Request authenticateProxy(Proxy proxy, Response response) throws IOException {         // Null indicates no attempt to authenticate.         return null;     } 

In TokenServiceHolder.java:

public class TokenServiceHolder {      TokenService tokenService = null;      @Nullable     public TokenService get() {         return tokenService;     }      public void set(TokenService tokenService) {         this.tokenService = tokenService;     } } 

Client setup:

//obtain instance of TokenServiceHolder from application or singleton-scoped component, then TokenAuthenticator authenticator = new TokenAuthenticator(tokenServiceHolder); OkHttpClient okHttpClient = new OkHttpClient();     okHttpClient.setAuthenticator(tokenAuthenticator);  Retrofit retrofit = new Retrofit.Builder()     .baseUrl("https://api.github.com/")     .client(okHttpClient)     .build();  TokenService tokenService = retrofit.create(TokenService.class); tokenServiceHolder.set(tokenService); 

If you are using Dagger 2 or a similar dependency injection framework there are some examples in the answers to this question

vote vote

64

Using TokenAuthenticator like @theblang answer is a correct way for handle refresh_token.

Here is my implement (I have using Kotlin, Dagger, RX but you may use this idea for implement to your case)
TokenAuthenticator

class TokenAuthenticator @Inject constructor(private val noneAuthAPI: PotoNoneAuthApi, private val accessTokenWrapper: AccessTokenWrapper) : Authenticator {      override fun authenticate(route: Route, response: Response): Request? {         val newAccessToken = noneAuthAPI.refreshToken(accessTokenWrapper.getAccessToken()!!.refreshToken).blockingGet()         accessTokenWrapper.saveAccessToken(newAccessToken) // save new access_token for next called         return response.request().newBuilder()                 .header("Authorization", newAccessToken.token) // just only need to override "Authorization" header, don't need to override all header since this new request is create base on old request                 .build()     } } 

For prevent dependency cycle like @Brais Gabin comment, I create 2 interface like

interface PotoNoneAuthApi { // NONE authentication API     @POST("/login")     fun login(@Body request: LoginRequest): Single<AccessToken>      @POST("refresh_token")     @FormUrlEncoded     fun refreshToken(@Field("refresh_token") refreshToken: String): Single<AccessToken> } 

and

interface PotoAuthApi { // Authentication API     @GET("api/images")     fun getImage(): Single<GetImageResponse> } 

AccessTokenWrapper class

class AccessTokenWrapper constructor(private val sharedPrefApi: SharedPrefApi) {     private var accessToken: AccessToken? = null      // get accessToken from cache or from SharePreference     fun getAccessToken(): AccessToken? {         if (accessToken == null) {             accessToken = sharedPrefApi.getObject(SharedPrefApi.ACCESS_TOKEN, AccessToken::class.java)         }         return accessToken     }      // save accessToken to SharePreference     fun saveAccessToken(accessToken: AccessToken) {         this.accessToken = accessToken         sharedPrefApi.putObject(SharedPrefApi.ACCESS_TOKEN, accessToken)     } } 

AccessToken class

data class AccessToken(         @Expose         var token: String,          @Expose         var refreshToken: String) 

My Interceptor

class AuthInterceptor @Inject constructor(private val accessTokenWrapper: AccessTokenWrapper): Interceptor {      override fun intercept(chain: Interceptor.Chain): Response {         val originalRequest = chain.request()         val authorisedRequestBuilder = originalRequest.newBuilder()                 .addHeader("Authorization", accessTokenWrapper.getAccessToken()!!.token)                 .header("Accept", "application/json")         return chain.proceed(authorisedRequestBuilder.build())     } } 

Finally, add Interceptor and Authenticator to your OKHttpClient when create service PotoAuthApi

Demo

https://github.com/PhanVanLinh/AndroidMVPKotlin

Note

Authenticator flow
  • Example API getImage() return 401 error code
  • authenticate method inside TokenAuthenticator will fired
  • Synchronize noneAuthAPI.refreshToken(...) called
  • After noneAuthAPI.refreshToken(...) response -> new token will add to header
  • getImage() will AUTO called with new header (HttpLogging WILL NOT log this call) (intercept inside AuthInterceptor WILL NOT CALLED)
  • If getImage() still failed with error 401, authenticate method inside TokenAuthenticator will fired AGAIN and AGAIN then it will throw error about call method many time(java.net.ProtocolException: Too many follow-up requests). You can prevent it by count response. Example, if you return null in authenticate after 3 times retry, getImage() will finish and return response 401

  • If getImage() response success => we will result the result normally (like you call getImage() with no error)

Hope it help

vote vote

51

I know this an old thread, but just in case someone stumbled in it.

TokenAuthenticator depends an a service class. The service class depends on an OkHttpClient instance. To create an OkHttpClient I need the TokenAuthenticator. How can I break this cycle? Two different OkHttpClients? They are going to have different connection pools..

I was facing the same problem, but I wanted to create only one OkHttpClient becuase I don't think that I need another one for just the TokenAuthenticator itself, I was using Dagger2, so I ended up providing the service class as Lazy injected in the TokenAuthenticator, you can read more about Lazy injection in dagger 2 here, but it's like basically saying to Dagger to NOT go and create the service needed by the TokenAuthenticator right away.

You can refer to this SO thread for sample code: How to resolve a circular dependency while still using Dagger2?

Top 3 video Explaining git svn - Checkout remote branch using git svn

Related QUESTION?