public void cloneRepo()

in plugin/src/com/microsoft/alm/plugin/idea/git/ui/simplecheckout/SimpleCheckoutModel.java [166:282]


    public void cloneRepo() {
        final ModelValidationInfo validationInfo = validate();
        if (validationInfo == null) {
            final Task.Backgroundable createCloneTask = new Task.Backgroundable(project, TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_DIALOG_TITLE),
                    true, PerformInBackgroundOption.DEAF) {
                final AtomicBoolean cloneResult = new AtomicBoolean();

                @Override
                public void run(@NotNull final ProgressIndicator progressIndicator) {
                    progressIndicator.setText(TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_DIALOG_TITLE));
                    // get context from manager, and store in active context
                    final ServerContext context = ServerContextManager.getInstance().getUpdatedContext(gitUrl, true);

                    if (context == null) {
                        logger.warn("No context could be found");
                        VcsNotifier.getInstance(project).notifyError(TfPluginBundle.message(TfPluginBundle.KEY_CHECKOUT_ERRORS_AUTHENTICATION_FAILED_TITLE), TfPluginBundle.message(TfPluginBundle.KEY_ERRORS_AUTH_NOT_SUCCESSFUL, gitUrl));
                        return;
                    }

                    final String gitRepositoryStr = context.getUsableGitUrl();
                    final Git git = ServiceManager.getService(Git.class);
                    logger.info("Cloning repo " + gitRepositoryStr);
                    cloneResult.set(git4idea.checkout.GitCheckoutProvider.doClone(project, git, getDirectoryName(), getParentDirectory(), gitRepositoryStr));
                }

                @Override
                public void onSuccess() {
                    logger.info("Simple clone was a success");
                    // if clone was successful then complete the checkout process which gives the option to open the project
                    if (cloneResult.get()) {
                        final VirtualFile destinationParent = LocalFileSystem.getInstance().findFileByIoFile(
                                new File(getParentDirectory()));
                        final File projectDirectory = new File(parentDirectory, directoryName);

                        DvcsUtil.addMappingIfSubRoot(project, FileUtil.join(new String[]{parentDirectory, directoryName}), "Git");
                        destinationParent.refresh(true, true, new Runnable() {
                            public void run() {
                                if (project.isOpen() && !project.isDisposed() && !project.isDefault()) {
                                    VcsDirtyScopeManager mgr = VcsDirtyScopeManager.getInstance(project);
                                    mgr.fileDirty(destinationParent);
                                }

                            }
                        });

                        listener.directoryCheckedOut(projectDirectory, GitVcs.getKey());
                        listener.checkoutCompleted();

                        // the project has changed since a new project was created above during the directoryCheckedOut process
                        // finding the new project based on the repo path
                        final Project currentProject = IdeaHelper.getCurrentProject();

                        // check if ref is not master and if currentProject is not null
                        // if currentProject is null that means the user chose not to create the project so not checking the branch out
                        if (StringUtils.isNotEmpty(ref) && !StringUtils.equals(ref, MASTER_BRANCH) && currentProject != null) {
                            logger.info("Non-master branch detected to checkout");
                            checkoutBranch(ref, currentProject, projectDirectory);
                        }
                    }
                }

                private void checkoutBranch(final String ref, final Project lastOpenedProject, final File projectDirectory) {
                    // adds a post initialization step to the project to checkout the given branch
                    final ProjectLevelVcsManagerImpl manager = (ProjectLevelVcsManagerImpl) ProjectLevelVcsManager.getInstance(lastOpenedProject);

                    // add step to refresh the root mapping so the new root is found for the repo
                    // TODO: refactor to use existing call instead of calling twice. Current call happens too late currently
                    // TODO: so that's why we need to call this beforehand so we can checkout the branch
                    manager.addInitializationRequest(VcsInitObject.MAPPINGS, new Runnable() {
                        @Override
                        public void run() {
                            manager.setDirectoryMapping(projectDirectory.getPath(), "Git");
                            manager.fireDirectoryMappingsChanged();
                        }
                    });

                    // step to checkout the desired branch
                    manager.addInitializationRequest(VcsInitObject.AFTER_COMMON, new DumbAwareRunnable() {
                        public void run() {
                            final GitRepositoryManager gitRepositoryManager = ServiceManager.getService(lastOpenedProject, GitRepositoryManager.class);
                            ArgumentHelper.checkNotNull(gitRepositoryManager, "GitRepositoryManager");
                            ArgumentHelper.checkNotNullOrEmpty(gitRepositoryManager.getRepositories(), "gitRepositoryManager.getRepositories()");
                            // TODO: use more direct manner to get repo but right now due to timing we can't
                            final GitRepository gitRepository = gitRepositoryManager.getRepositories().get(0);
                            ArgumentHelper.checkNotNull(gitRepository, "GitRepository");
                            String fullRefName = StringUtils.EMPTY;

                            // find remote red name from given name
                            for (final GitRemoteBranch remoteBranch : gitRepository.getInfo().getRemoteBranches()) {
                                final String remoteBranchName = remoteBranch.getName().replaceFirst(remoteBranch.getRemote().getName() + "/", StringUtils.EMPTY);
                                if (ref.equals(remoteBranchName)) {
                                    fullRefName = remoteBranch.getName();
                                }
                            }

                            if (StringUtils.isNotEmpty(fullRefName)) {
                                final String remoteRef = fullRefName;
                                // Checking out a branch using the brancher has to start on the UI thread but moves to the background
                                IdeaHelper.runOnUIThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        logger.info("Checking out branch " + remoteRef);
                                        final GitBrancher brancher = ServiceManager.getService(lastOpenedProject, GitBrancher.class);
                                        brancher.checkoutNewBranchStartingFrom(ref, remoteRef,
                                                Collections.singletonList(gitRepository), null);
                                    }
                                });
                            } else {
                                throw new IllegalArgumentException(String.format("Ref %s was not found remotely so could not be checked out.", fullRefName));
                            }
                        }
                    });
                }
            };
            createCloneTask.queue();
        }
    }