Skip to content

Commit

Permalink
Merge pull request #42 from dolthub/taylor/pulls
Browse files Browse the repository at this point in the history
Add pull requests tab
  • Loading branch information
tbantle22 authored Nov 9, 2023
2 parents b308ae5 + 798360f commit b853fe5
Show file tree
Hide file tree
Showing 106 changed files with 2,756 additions and 218 deletions.
1 change: 1 addition & 0 deletions packages/graphql-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"mysql2": "^3.1.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.5.4",
"timeago.js": "^4.0.2",
"typeorm": "^0.3.12"
},
"devDependencies": {
Expand Down
44 changes: 41 additions & 3 deletions packages/graphql-server/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,42 @@ type DocList {
list: [Doc!]!
}

type PullSummary {
_id: ID!
commits: CommitList!
}

type PullWithDetails {
_id: ID!
state: PullState!
summary: PullSummary
details: [PullDetails!]
}

enum PullState {
Open
Merged
Unspecified
}

union PullDetails = PullDetailSummary | PullDetailCommit

type PullDetailSummary {
_id: ID!
username: String!
createdAt: Timestamp!
numCommits: Float!
}

type PullDetailCommit {
_id: ID!
username: String!
message: String!
createdAt: Timestamp!
commitId: String!
parentCommitId: String
}

type RowDiff {
added: Row
deleted: Row
Expand Down Expand Up @@ -229,7 +265,7 @@ type Query {
branchOrDefault(databaseName: String!, branchName: String): Branch
branches(databaseName: String!, sortBy: SortBranchesBy): BranchNamesList!
defaultBranch(databaseName: String!): Branch
commits(offset: Int, databaseName: String!, refName: String, afterCommitId: String): CommitList!
commits(offset: Int, databaseName: String!, refName: String, afterCommitId: String, twoDot: Boolean, excludingCommitsFromRefName: String): CommitList!
currentDatabase: String
hasDatabaseEnv: Boolean!
databases: [String!]!
Expand All @@ -238,9 +274,10 @@ type Query {
diffSummaries(databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, type: CommitDiffType, tableName: String): [DiffSummary!]!
docs(databaseName: String!, refName: String!): DocList!
docOrDefaultDoc(refName: String!, databaseName: String!, docType: DocType): Doc
rowDiffs(offset: Int, databaseName: String!, fromCommitId: String!, toCommitId: String!, refName: String, tableName: String!, filterByRowType: DiffRowType): RowDiffList!
pullWithDetails(databaseName: String!, fromBranchName: String!, toBranchName: String!): PullWithDetails!
rowDiffs(offset: Int, databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, filterByRowType: DiffRowType, type: CommitDiffType): RowDiffList!
rows(refName: String!, databaseName: String!, tableName: String!, offset: Int): RowList!
schemaDiff(databaseName: String!, fromCommitId: String!, toCommitId: String!, refName: String, tableName: String!): SchemaDiff
schemaDiff(databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, type: CommitDiffType): SchemaDiff
doltSchemas(databaseName: String!, refName: String!): [SchemaItem!]!
views(databaseName: String!, refName: String!): [SchemaItem!]!
doltProcedures(databaseName: String!, refName: String!): [SchemaItem!]!
Expand Down Expand Up @@ -285,6 +322,7 @@ type Mutation {
createDatabase(databaseName: String!): Boolean!
resetDatabase: Boolean!
loadDataFile(tableName: String!, refName: String!, databaseName: String!, importOp: ImportOperation!, fileType: FileType!, file: Upload!, modifier: LoadDataModifier): Boolean!
mergePull(databaseName: String!, fromBranchName: String!, toBranchName: String!): Boolean!
createTag(tagName: String!, databaseName: String!, message: String, fromRefName: String!): Tag!
deleteTag(databaseName: String!, tagName: String!): Boolean!
}
Expand Down
2 changes: 2 additions & 0 deletions packages/graphql-server/src/commits/commit.queries.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export const doltLogsQuery = `SELECT * FROM DOLT_LOG(?, '--parents') LIMIT ? OFFSET ?`;

export const twoDotDoltLogsQuery = `SELECT * FROM DOLT_LOG(?, '--parents')`;
39 changes: 21 additions & 18 deletions packages/graphql-server/src/commits/commit.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DataSourceService } from "../dataSources/dataSource.service";
import { ROW_LIMIT, getNextOffset } from "../utils";
import { DBArgsWithOffset, RawRow } from "../utils/commonTypes";
import { Commit, CommitList, fromDoltLogRow } from "./commit.model";
import { doltLogsQuery } from "./commit.queries";
import { doltLogsQuery, twoDotDoltLogsQuery } from "./commit.queries";

@ArgsType()
export class ListCommitsArgs extends DBArgsWithOffset {
Expand All @@ -14,14 +14,11 @@ export class ListCommitsArgs extends DBArgsWithOffset {
@Field({ nullable: true })
afterCommitId?: string;

// @Field(_type => Boolean, { nullable: true })
// twoDot?: boolean;
@Field(_type => Boolean, { nullable: true })
twoDot?: boolean;

// @Field({ nullable: true })
// excludingCommitsFromRefName?: string;

// @Field(_type => Boolean, { nullable: true })
// resolveBranchNames?: boolean;
@Field({ nullable: true })
excludingCommitsFromRefName?: string;
}

@Resolver(_of => Commit)
Expand All @@ -38,6 +35,12 @@ export class CommitResolver {
const refName = args.refName ?? args.afterCommitId ?? "";
const offset = args.offset ?? 0;
return this.dss.query(async query => {
if (args.twoDot && args.excludingCommitsFromRefName) {
const logs = await query(twoDotDoltLogsQuery, [
`${args.excludingCommitsFromRefName}..${refName}`,
]);
return getCommitListRes(logs, args);
}
const logs = await query(doltLogsQuery, [refName, ROW_LIMIT + 1, offset]);
return getCommitListRes(logs, args);
}, args.databaseName);
Expand All @@ -64,15 +67,15 @@ function handleArgsErr(args: ListCommitsArgs): Error | undefined {
"cannot supply both `refName` and `afterCommitId` when listing commits",
);
}
// if (args.twoDot && !args.excludingCommitsFromRefName) {
// return new Error(
// "must supply `excludingCommitsFromRefName` if twoDot is true",
// );
// }
// if (!args.twoDot && args.excludingCommitsFromRefName) {
// return new Error(
// "cannot supply `excludingCommitsFromRefName` if twoDot is not provided or false",
// );
// }
if (args.twoDot && !args.excludingCommitsFromRefName) {
return new Error(
"must supply `excludingCommitsFromRefName` if twoDot is true",
);
}
if (!args.twoDot && args.excludingCommitsFromRefName) {
return new Error(
"cannot supply `excludingCommitsFromRefName` if twoDot is not provided or false",
);
}
return undefined;
}
90 changes: 90 additions & 0 deletions packages/graphql-server/src/pullDetails/getPullDetails.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { format } from "timeago.js";
import { Commit } from "../commits/commit.model";
import { PullSummary } from "../pullSummaries/pullSummary.model";
import {
PullDetailCommit,
PullDetails,
PullDetailSummary,
PullDetailUnion,
} from "./pullDetail.model";

type PullDetail = typeof PullDetailUnion;

export default function getPullDetails(summary?: PullSummary): PullDetails {
const details: PullDetails = [];
if (!summary) {
return details;
}
// Add commits to details
summary.commits.list.forEach(c => details.push(getCommit(c)));
// Get commit summaries from sorted commits
const sorted = details.sort(sortByTimestampDesc);
const summaries = getSummaries(sorted);
return sorted.concat(summaries).sort(sortByTimestampDesc) as PullDetails;
}

function sortByTimestampDesc(a: PullDetail, b: PullDetail) {
return a.createdAt.valueOf() - b.createdAt.valueOf();
}

function getCommit(c: Commit): PullDetailCommit {
const parentCommitId = c.parents.length ? c.parents[0] : undefined;
return {
...c,
username: c.committer.username ?? c.committer.displayName,
createdAt: c.committedAt,
parentCommitId,
};
}

const initialSummary: PullDetailSummary = {
_id: "",
username: "",
createdAt: new Date(0),
numCommits: 0,
};

function getSummaries(sorted: PullDetail[]): PullDetailSummary[] {
const summaries: PullDetailSummary[] = [];
let summary = { ...initialSummary };

sorted.forEach(d => {
// Only update summary for commits
if ("commitId" in d) {
const timeagosEqual = format(d.createdAt) === format(summary.createdAt);
const needToUpdate = d.username !== summary.username || !timeagosEqual;

if (needToUpdate) {
// Push last summary if it has commit info
if (summary.numCommits > 0) {
summaries.push({ ...summary });
}
// Update summary with changed information
summary = {
...summary,
_id: `${d.username}/${d.createdAt.valueOf()}`,
username: d.username,
numCommits: 0,
// Ensure that the summary shows up before first commit
createdAt: new Date(d.createdAt.valueOf() - 1),
};
}
// Update number of commits every time
summary.numCommits += 1;
} else {
// If not commit, push last summary
if (summary.numCommits > 0) {
summaries.push({ ...summary });
}
// And start fresh
summary = { ...initialSummary };
}
});

// If last summary not pushed yet, push
if (summary.numCommits > 0) {
summaries.push({ ...summary });
}

return summaries;
}
60 changes: 60 additions & 0 deletions packages/graphql-server/src/pullDetails/pullDetail.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import {
Field,
GraphQLTimestamp,
ID,
ObjectType,
createUnionType,
} from "@nestjs/graphql";

@ObjectType()
export class PullDetailCommit {
@Field(_type => ID)
_id: string;

@Field()
username: string;

@Field()
message: string;

@Field(_type => GraphQLTimestamp)
createdAt: Date;

@Field()
commitId: string;

@Field({ nullable: true })
parentCommitId?: string;
}

@ObjectType()
export class PullDetailSummary {
@Field(_type => ID)
_id: string;

@Field()
username: string;

@Field(_type => GraphQLTimestamp)
createdAt: Date;

@Field()
numCommits: number;
}

export const PullDetailUnion = createUnionType({
name: "PullDetails",
types: () => [PullDetailSummary, PullDetailCommit],
resolveType: value => {
if ("commitId" in value) {
return PullDetailCommit;
}
if ("numCommits" in value) {
return PullDetailSummary;
}
return undefined;
},
});

export type PullDetail = typeof PullDetailUnion;
export type PullDetails = PullDetail[];
21 changes: 21 additions & 0 deletions packages/graphql-server/src/pullSummaries/pullSummary.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Field, ID, ObjectType } from "@nestjs/graphql";
import * as commit from "../commits/commit.model";

@ObjectType()
export class PullSummary {
@Field(_type => ID)
_id: string;

@Field(_type => commit.CommitList)
commits: commit.CommitList;
}

export function fromAPISummary(
_pullId: string,
commits: commit.Commit[],
): PullSummary {
return {
_id: `${_pullId}/summary`,
commits: { list: commits },
};
}
9 changes: 9 additions & 0 deletions packages/graphql-server/src/pulls/pull.enums.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { registerEnumType } from "@nestjs/graphql";

export enum PullState {
Open,
Merged,
Unspecified,
}

registerEnumType(PullState, { name: "PullState" });
37 changes: 37 additions & 0 deletions packages/graphql-server/src/pulls/pull.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Field, ID, ObjectType } from "@nestjs/graphql";
import { Commit } from "../commits/commit.model";
import getPullDetails from "../pullDetails/getPullDetails";
import { PullDetailUnion, PullDetails } from "../pullDetails/pullDetail.model";
import {
PullSummary,
fromAPISummary,
} from "../pullSummaries/pullSummary.model";
import { PullState } from "./pull.enums";

@ObjectType()
export class PullWithDetails {
@Field(_type => ID)
_id: string;

@Field(_type => PullState)
state: PullState;

@Field(_type => PullSummary, { nullable: true })
summary?: PullSummary;

@Field(_type => [PullDetailUnion], { nullable: true })
details?: PullDetails;
}

export function fromAPIModelPullWithDetails(
pullId: string,
commits: Commit[] = [],
): PullWithDetails {
const summary = fromAPISummary(pullId, commits);
return {
_id: `${pullId}/pullWithDetails`,
state: commits.length ? PullState.Open : PullState.Merged,
summary,
details: getPullDetails(summary),
};
}
1 change: 1 addition & 0 deletions packages/graphql-server/src/pulls/pull.queries.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const callMerge = `CALL DOLT_MERGE(?, "--no-ff", "-m", ?)`;
Loading

0 comments on commit b853fe5

Please sign in to comment.