blob: b5402a70fbe91002dea298b6ec13aa3f5ffda58d [file] [log] [blame]
// Copyright 2023 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:io';
import 'package:auto_submit/service/log.dart';
import 'package:github/github.dart';
import 'git_cli.dart';
import 'utilities.dart';
class GitRepositoryManager {
final RepositorySlug slug;
final String workingDirectory;
String? cloneToDirectory;
final GitCli gitCli;
late String targetCloneDirectory;
/// RepositoryManager will perform clone, revert and delete on the repository
/// in the working directory that is cloned to [cloneToDirectory].
///
/// If the clonedToDirectory is not provided then the name of the repository
/// will be used as the cloneToDirectory.
GitRepositoryManager({
required this.slug,
//path/to/working/directory
required this.workingDirectory,
//reponame_commitSha
this.cloneToDirectory,
required this.gitCli,
}) {
cloneToDirectory ??= slug.name;
targetCloneDirectory = '$workingDirectory/$cloneToDirectory';
}
/// Clone the repository identified by the slug.
///
/// Throw out rather than decomposing the return codes from the ProcessResult.
Future<void> cloneRepository() async {
if (Directory(targetCloneDirectory).existsSync()) {
// Blow the directory away instead of trying to update it.
Directory(targetCloneDirectory).deleteSync(recursive: true);
}
// Checking out a sparse copy will not checkout source files but will still
// allow a revert since we only care about the commitSha.
// Source: https://git-scm.com/docs/git-clone
await gitCli.cloneRepository(
slug: slug,
workingDirectory: workingDirectory,
targetDirectory: targetCloneDirectory,
options: ['--sparse'],
);
}
Future<void> setupConfig() async {
await gitCli.setupUserConfig(slug: slug, workingDirectory: targetCloneDirectory);
await gitCli.setupUserEmailConfig(slug: slug, workingDirectory: targetCloneDirectory);
}
/// Revert a commit in the current repository.
///
/// The [baseBranchName] is the branch we want to branch from. In this case it
/// will almost always be the default branch name. The target branch is
/// preformatted with the commitSha.
Future<void> revertCommit(String baseBranchName, String commitSha, RepositorySlug slug, String token) async {
final GitRevertBranchName revertBranchName = GitRevertBranchName(commitSha);
// Working directory for these must be repo checkout directory.
// Check out the baseBranchName before doing anything.
await gitCli.createBranch(
newBranchName: revertBranchName.branch,
workingDirectory: targetCloneDirectory,
useCheckout: true,
);
await gitCli.setUpstream(
slug: slug,
workingDirectory: targetCloneDirectory,
branchName: revertBranchName.branch,
token: token,
);
await gitCli.revertChange(
commitSha: commitSha,
workingDirectory: targetCloneDirectory,
);
await gitCli.pushBranch(
branchName: revertBranchName.branch,
workingDirectory: targetCloneDirectory,
);
}
/// Delete the repository managed by this instance.
Future<void> deleteRepository() async {
log.info('Deleting clone directory $targetCloneDirectory');
if (Directory(targetCloneDirectory).existsSync()) {
Directory(targetCloneDirectory).deleteSync(recursive: true);
}
}
}