ghstack 0.9.3__tar.gz → 0.9.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ghstack-0.9.3/README.md → ghstack-0.9.5/PKG-INFO +25 -46
- ghstack-0.9.3/PKG-INFO → ghstack-0.9.5/README.md +5 -72
- ghstack-0.9.5/pyproject.toml +49 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/action.py +1 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/checkout.py +3 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/cli.py +12 -6
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/config.py +12 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/diff.py +2 -2
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/forensics.py +1 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/github.py +1 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/github_utils.py +16 -2
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/land.py +3 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/shell.py +1 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/status.py +1 -1
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/submit.py +57 -39
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/test_prelude.py +1 -1
- ghstack-0.9.3/LICENSE +0 -19
- ghstack-0.9.3/ghstack/inbox.py +0 -7
- ghstack-0.9.3/pyproject.toml +0 -44
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/__init__.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/__main__.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/cache.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/circleci.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/circleci_real.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/git.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/github_fake.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/github_real.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/github_schema.graphql +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/gpg_sign.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/logs.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/py.typed +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/rage.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/types.py +0 -0
- {ghstack-0.9.3 → ghstack-0.9.5/src}/ghstack/unlink.py +0 -0
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ghstack
|
|
3
|
+
Version: 0.9.5
|
|
4
|
+
Summary: Stack diff support for GitHub
|
|
5
|
+
Author: Edward Z. Yang
|
|
6
|
+
Author-email: Edward Z. Yang <ezyang@mit.edu>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Dist: aiohttp>=3,<4
|
|
12
|
+
Requires-Dist: importlib-metadata>=1.4 ; python_full_version < '3.8'
|
|
13
|
+
Requires-Dist: requests>=2,<3
|
|
14
|
+
Requires-Dist: typing-extensions>=3
|
|
15
|
+
Requires-Dist: click>=8,<9
|
|
16
|
+
Requires-Dist: flake8>=7.0.0,<8.0.0
|
|
17
|
+
Requires-Python: >=3.8.1, <4.0.0
|
|
18
|
+
Project-URL: repository, https://github.com/ezyang/ghstack
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
1
21
|
# ghstack
|
|
2
22
|
|
|
3
23
|
Conveniently submit stacks of diffs to GitHub as separate pull requests.
|
|
@@ -51,7 +71,11 @@ branch, and start working on a fresh branch.
|
|
|
51
71
|
|
|
52
72
|
**WARNING.** You will NOT be able to merge these commits using the
|
|
53
73
|
normal GitHub UI, as their branch bases won't be master. Use
|
|
54
|
-
`ghstack land $PR_URL`
|
|
74
|
+
`ghstack land $PR_URL` (or alternatively `ghstack land #PR_NUM`) to land
|
|
75
|
+
a ghstack'ed pull request.
|
|
76
|
+
|
|
77
|
+
You can also setup a GitHub action to allow a bot land.
|
|
78
|
+
https://github.com/Chillee/ghstack_land_example/blob/main/.github/workflows/issue_comment.yml is an end-to-end example of how to do this.
|
|
55
79
|
|
|
56
80
|
## Structure of submitted pull requests
|
|
57
81
|
|
|
@@ -73,51 +97,6 @@ pull request and pushes commits onto three branches:
|
|
|
73
97
|
want to work on the commits from another machine, this is the best way
|
|
74
98
|
to get it.
|
|
75
99
|
|
|
76
|
-
## Developer notes
|
|
77
|
-
|
|
78
|
-
This project uses [Poetry](https://python-poetry.org/docs/#installation), so
|
|
79
|
-
after you've installed Poetry itself, run this command in your clone of this
|
|
80
|
-
repo to install all the dependencies you need for working on `ghstack`:
|
|
81
|
-
```
|
|
82
|
-
poetry install
|
|
83
|
-
```
|
|
84
|
-
Note that this installs the dependencies (and `ghstack` itself) in an isolated
|
|
85
|
-
Python virtual environment rather than globally. If your cwd is in your clone of
|
|
86
|
-
this repo then you can run your locally-built `ghstack` using `poetry run
|
|
87
|
-
ghstack $ARGS`, but if you want to run it from somewhere else, you probably want
|
|
88
|
-
[`poetry shell`](https://python-poetry.org/docs/cli/#shell) instead:
|
|
89
|
-
```
|
|
90
|
-
poetry shell
|
|
91
|
-
cd $SOMEWHERE
|
|
92
|
-
ghstack $ARGS
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Testing
|
|
96
|
-
|
|
97
|
-
We have tests, using a mock GitHub GraphQL server! How cool is that?
|
|
98
|
-
```
|
|
99
|
-
poetry run python test_ghstack.py
|
|
100
|
-
```
|
|
101
|
-
That runs most of the tests; you can run all tests (including lints) like this:
|
|
102
|
-
```
|
|
103
|
-
poetry run python run_tests.py
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
### Publishing
|
|
107
|
-
|
|
108
|
-
You can also [use Poetry to
|
|
109
|
-
publish](https://python-poetry.org/docs/cli/#publish) to a package repository.
|
|
110
|
-
For instance, if you've configured your [Poetry
|
|
111
|
-
repositories](https://python-poetry.org/docs/repositories/) like this:
|
|
112
|
-
```
|
|
113
|
-
poetry config repositories.testpypi https://test.pypi.org/legacy/
|
|
114
|
-
```
|
|
115
|
-
Then you can publish to TestPyPI like this:
|
|
116
|
-
```
|
|
117
|
-
poetry publish --build --repository testpypi
|
|
118
|
-
```
|
|
119
|
-
To publish to PyPI itself, just omit the `--repository` argument.
|
|
120
|
-
|
|
121
100
|
## Design constraints
|
|
122
101
|
|
|
123
102
|
There are some weird aspects about GitHub's design which lead to unusual
|
|
@@ -1,28 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: ghstack
|
|
3
|
-
Version: 0.9.3
|
|
4
|
-
Summary: Stack diff support for GitHub
|
|
5
|
-
Home-page: https://github.com/ezyang/ghstack
|
|
6
|
-
License: MIT
|
|
7
|
-
Author: Edward Z. Yang
|
|
8
|
-
Author-email: ezyang@mit.edu
|
|
9
|
-
Requires-Python: >=3.8.1,<4.0.0
|
|
10
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
-
Classifier: Operating System :: OS Independent
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Requires-Dist: aiohttp (>=3,<4)
|
|
18
|
-
Requires-Dist: click (>=8,<9)
|
|
19
|
-
Requires-Dist: flake8 (>=7.0.0,<8.0.0)
|
|
20
|
-
Requires-Dist: importlib-metadata (>=1.4) ; python_version < "3.8"
|
|
21
|
-
Requires-Dist: requests (>=2,<3)
|
|
22
|
-
Requires-Dist: typing-extensions (>=3,<5)
|
|
23
|
-
Project-URL: Repository, https://github.com/ezyang/ghstack
|
|
24
|
-
Description-Content-Type: text/markdown
|
|
25
|
-
|
|
26
1
|
# ghstack
|
|
27
2
|
|
|
28
3
|
Conveniently submit stacks of diffs to GitHub as separate pull requests.
|
|
@@ -76,7 +51,11 @@ branch, and start working on a fresh branch.
|
|
|
76
51
|
|
|
77
52
|
**WARNING.** You will NOT be able to merge these commits using the
|
|
78
53
|
normal GitHub UI, as their branch bases won't be master. Use
|
|
79
|
-
`ghstack land $PR_URL`
|
|
54
|
+
`ghstack land $PR_URL` (or alternatively `ghstack land #PR_NUM`) to land
|
|
55
|
+
a ghstack'ed pull request.
|
|
56
|
+
|
|
57
|
+
You can also setup a GitHub action to allow a bot land.
|
|
58
|
+
https://github.com/Chillee/ghstack_land_example/blob/main/.github/workflows/issue_comment.yml is an end-to-end example of how to do this.
|
|
80
59
|
|
|
81
60
|
## Structure of submitted pull requests
|
|
82
61
|
|
|
@@ -98,51 +77,6 @@ pull request and pushes commits onto three branches:
|
|
|
98
77
|
want to work on the commits from another machine, this is the best way
|
|
99
78
|
to get it.
|
|
100
79
|
|
|
101
|
-
## Developer notes
|
|
102
|
-
|
|
103
|
-
This project uses [Poetry](https://python-poetry.org/docs/#installation), so
|
|
104
|
-
after you've installed Poetry itself, run this command in your clone of this
|
|
105
|
-
repo to install all the dependencies you need for working on `ghstack`:
|
|
106
|
-
```
|
|
107
|
-
poetry install
|
|
108
|
-
```
|
|
109
|
-
Note that this installs the dependencies (and `ghstack` itself) in an isolated
|
|
110
|
-
Python virtual environment rather than globally. If your cwd is in your clone of
|
|
111
|
-
this repo then you can run your locally-built `ghstack` using `poetry run
|
|
112
|
-
ghstack $ARGS`, but if you want to run it from somewhere else, you probably want
|
|
113
|
-
[`poetry shell`](https://python-poetry.org/docs/cli/#shell) instead:
|
|
114
|
-
```
|
|
115
|
-
poetry shell
|
|
116
|
-
cd $SOMEWHERE
|
|
117
|
-
ghstack $ARGS
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
### Testing
|
|
121
|
-
|
|
122
|
-
We have tests, using a mock GitHub GraphQL server! How cool is that?
|
|
123
|
-
```
|
|
124
|
-
poetry run python test_ghstack.py
|
|
125
|
-
```
|
|
126
|
-
That runs most of the tests; you can run all tests (including lints) like this:
|
|
127
|
-
```
|
|
128
|
-
poetry run python run_tests.py
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
### Publishing
|
|
132
|
-
|
|
133
|
-
You can also [use Poetry to
|
|
134
|
-
publish](https://python-poetry.org/docs/cli/#publish) to a package repository.
|
|
135
|
-
For instance, if you've configured your [Poetry
|
|
136
|
-
repositories](https://python-poetry.org/docs/repositories/) like this:
|
|
137
|
-
```
|
|
138
|
-
poetry config repositories.testpypi https://test.pypi.org/legacy/
|
|
139
|
-
```
|
|
140
|
-
Then you can publish to TestPyPI like this:
|
|
141
|
-
```
|
|
142
|
-
poetry publish --build --repository testpypi
|
|
143
|
-
```
|
|
144
|
-
To publish to PyPI itself, just omit the `--repository` argument.
|
|
145
|
-
|
|
146
80
|
## Design constraints
|
|
147
81
|
|
|
148
82
|
There are some weird aspects about GitHub's design which lead to unusual
|
|
@@ -189,4 +123,3 @@ So, this is not impossible to do, but it will need some work.
|
|
|
189
123
|
You have to work out what the real base commit is, whether
|
|
190
124
|
or not you need to advance it, and also rewrite the stack rendering
|
|
191
125
|
code.
|
|
192
|
-
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
authors = [
|
|
3
|
+
{name = "Edward Z. Yang", email = "ezyang@mit.edu"},
|
|
4
|
+
]
|
|
5
|
+
license = {text = "MIT"}
|
|
6
|
+
requires-python = "<4.0.0,>=3.8.1"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"aiohttp<4,>=3",
|
|
9
|
+
"importlib-metadata>=1.4; python_version < \"3.8\"",
|
|
10
|
+
"requests<3,>=2",
|
|
11
|
+
"typing-extensions>=3",
|
|
12
|
+
"click<9,>=8",
|
|
13
|
+
"flake8<8.0.0,>=7.0.0",
|
|
14
|
+
]
|
|
15
|
+
name = "ghstack"
|
|
16
|
+
version = "0.9.5"
|
|
17
|
+
description = "Stack diff support for GitHub"
|
|
18
|
+
readme = "README.md"
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"License :: OSI Approved :: MIT License",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
repository = "https://github.com/ezyang/ghstack"
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
ghstack = "ghstack.cli:main"
|
|
30
|
+
|
|
31
|
+
[dependency-groups]
|
|
32
|
+
dev = [
|
|
33
|
+
"black<25.0.0,>=24.3.0",
|
|
34
|
+
"flake8<8,>=7",
|
|
35
|
+
"graphql-core<4,>=3",
|
|
36
|
+
"hypothesis<7,>=6",
|
|
37
|
+
"mypy<2,>=1",
|
|
38
|
+
"pytest<8,>=7",
|
|
39
|
+
"usort<2,>=1",
|
|
40
|
+
"ufmt<3,>=2",
|
|
41
|
+
"lintrunner<1.0.0,>=0.11.0",
|
|
42
|
+
"types-requests<3.0.0.0,>=2.31.0.10",
|
|
43
|
+
"pytest-xdist<4.0.0,>=3.5.0",
|
|
44
|
+
"expecttest<1.0.0,>=0.2.0",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[build-system]
|
|
48
|
+
requires = ["uv_build>=0.6,<0.7"]
|
|
49
|
+
build-backend = "uv_build"
|
|
@@ -15,7 +15,9 @@ def main(
|
|
|
15
15
|
remote_name: str,
|
|
16
16
|
) -> None:
|
|
17
17
|
|
|
18
|
-
params = ghstack.github_utils.parse_pull_request(
|
|
18
|
+
params = ghstack.github_utils.parse_pull_request(
|
|
19
|
+
pull_request, sh=sh, remote_name=remote_name
|
|
20
|
+
)
|
|
19
21
|
head_ref = github.get_head_ref(**params)
|
|
20
22
|
orig_ref = re.sub(r"/head$", "/orig", head_ref)
|
|
21
23
|
if orig_ref == head_ref:
|
|
@@ -57,7 +57,9 @@ def cli_context(
|
|
|
57
57
|
@click.option("--force", is_flag=True, hidden=True)
|
|
58
58
|
@click.option("--no-skip", is_flag=True, hidden=True)
|
|
59
59
|
@click.option("--draft", is_flag=True, hidden=True)
|
|
60
|
-
@click.option(
|
|
60
|
+
@click.option(
|
|
61
|
+
"--direct/--no-direct", "direct_opt", is_flag=True, hidden=True, default=None
|
|
62
|
+
)
|
|
61
63
|
@click.option("--base", "-B", default=None, hidden=True)
|
|
62
64
|
@click.option("--stack/--no-stack", "-s/-S", is_flag=True, default=True, hidden=True)
|
|
63
65
|
def main(
|
|
@@ -67,7 +69,7 @@ def main(
|
|
|
67
69
|
update_fields: bool,
|
|
68
70
|
short: bool,
|
|
69
71
|
force: bool,
|
|
70
|
-
|
|
72
|
+
direct_opt: Optional[bool],
|
|
71
73
|
no_skip: bool,
|
|
72
74
|
draft: bool,
|
|
73
75
|
base: Optional[str],
|
|
@@ -89,7 +91,7 @@ def main(
|
|
|
89
91
|
draft=draft,
|
|
90
92
|
base=base,
|
|
91
93
|
stack=stack,
|
|
92
|
-
|
|
94
|
+
direct_opt=direct_opt,
|
|
93
95
|
)
|
|
94
96
|
|
|
95
97
|
|
|
@@ -226,7 +228,11 @@ def status(pull_request: str) -> None:
|
|
|
226
228
|
"listed in the command line.",
|
|
227
229
|
)
|
|
228
230
|
@click.option(
|
|
229
|
-
"--direct",
|
|
231
|
+
"--direct/--no-direct",
|
|
232
|
+
"direct_opt",
|
|
233
|
+
default=None,
|
|
234
|
+
is_flag=True,
|
|
235
|
+
help="Create stack that directly merges into master",
|
|
230
236
|
)
|
|
231
237
|
@click.argument(
|
|
232
238
|
"revs",
|
|
@@ -240,7 +246,7 @@ def submit(
|
|
|
240
246
|
force: bool,
|
|
241
247
|
no_skip: bool,
|
|
242
248
|
draft: bool,
|
|
243
|
-
|
|
249
|
+
direct_opt: Optional[bool],
|
|
244
250
|
base: Optional[str],
|
|
245
251
|
revs: Tuple[str, ...],
|
|
246
252
|
stack: bool,
|
|
@@ -264,7 +270,7 @@ def submit(
|
|
|
264
270
|
base_opt=base,
|
|
265
271
|
revs=revs,
|
|
266
272
|
stack=stack,
|
|
267
|
-
|
|
273
|
+
direct_opt=direct_opt,
|
|
268
274
|
)
|
|
269
275
|
|
|
270
276
|
|
|
@@ -12,6 +12,9 @@ import requests
|
|
|
12
12
|
|
|
13
13
|
import ghstack.logs
|
|
14
14
|
|
|
15
|
+
DEFAULT_GHSTACKRC_PATH = Path.home() / ".ghstackrc"
|
|
16
|
+
GHSTACKRC_PATH_VAR = "GHSTACKRC_PATH"
|
|
17
|
+
|
|
15
18
|
Config = NamedTuple(
|
|
16
19
|
"Config",
|
|
17
20
|
[
|
|
@@ -41,6 +44,12 @@ Config = NamedTuple(
|
|
|
41
44
|
)
|
|
42
45
|
|
|
43
46
|
|
|
47
|
+
def get_path_from_env_var(var_name: str) -> Optional[Path]:
|
|
48
|
+
if (path := os.environ.get(var_name)) is not None:
|
|
49
|
+
return Path(path).expanduser().resolve()
|
|
50
|
+
return None
|
|
51
|
+
|
|
52
|
+
|
|
44
53
|
def read_config(
|
|
45
54
|
*,
|
|
46
55
|
request_circle_token: bool = False,
|
|
@@ -60,7 +69,9 @@ def read_config(
|
|
|
60
69
|
|
|
61
70
|
write_back = False
|
|
62
71
|
if config_path is None:
|
|
63
|
-
config_path =
|
|
72
|
+
config_path = str(
|
|
73
|
+
get_path_from_env_var(GHSTACKRC_PATH_VAR) or DEFAULT_GHSTACKRC_PATH
|
|
74
|
+
)
|
|
64
75
|
write_back = True
|
|
65
76
|
|
|
66
77
|
logging.debug(f"config_path = {config_path}")
|
|
@@ -14,7 +14,7 @@ RE_GH_METADATA = re.compile(
|
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
RAW_PULL_REQUEST_RESOLVED = (
|
|
17
|
-
r"Pull Request resolved: "
|
|
17
|
+
r"(Pull Request resolved|Pull-Request-resolved): "
|
|
18
18
|
r"https://{github_url}/(?P<owner>[^/]+)/(?P<repo>[^/]+)/pull/(?P<number>[0-9]+)"
|
|
19
19
|
)
|
|
20
20
|
|
|
@@ -93,7 +93,7 @@ class Diff:
|
|
|
93
93
|
# be the same.
|
|
94
94
|
source_id: str
|
|
95
95
|
|
|
96
|
-
# The contents of 'Pull
|
|
96
|
+
# The contents of 'Pull-Request-resolved'. This is None for
|
|
97
97
|
# diffs that haven't been submitted by ghstack. For BC reasons,
|
|
98
98
|
# this also accepts gh-metadata.
|
|
99
99
|
pull_request_resolved: Optional[PullRequestResolved]
|
|
@@ -27,7 +27,7 @@ def get_github_repo_name_with_owner(
|
|
|
27
27
|
# Grovel in remotes to figure it out
|
|
28
28
|
remote_url = sh.git("remote", "get-url", remote_name)
|
|
29
29
|
while True:
|
|
30
|
-
match = r"^git@{github_url}
|
|
30
|
+
match = r"^git@{github_url}:/?([^/]+)/(.+?)(?:\.git)?$".format(
|
|
31
31
|
github_url=github_url
|
|
32
32
|
)
|
|
33
33
|
m = re.match(match, remote_url)
|
|
@@ -115,9 +115,23 @@ GitHubPullRequestParams = TypedDict(
|
|
|
115
115
|
)
|
|
116
116
|
|
|
117
117
|
|
|
118
|
-
def parse_pull_request(
|
|
118
|
+
def parse_pull_request(
|
|
119
|
+
pull_request: str,
|
|
120
|
+
*,
|
|
121
|
+
sh: Optional[ghstack.shell.Shell] = None,
|
|
122
|
+
remote_name: Optional[str] = None,
|
|
123
|
+
) -> GitHubPullRequestParams:
|
|
119
124
|
m = RE_PR_URL.match(pull_request)
|
|
120
125
|
if not m:
|
|
126
|
+
# We can reconstruct the URL if just a PR number is passed
|
|
127
|
+
if sh is not None and remote_name is not None:
|
|
128
|
+
remote_url = sh.git("remote", "get-url", remote_name)
|
|
129
|
+
# Do not pass the shell to avoid infinite loop
|
|
130
|
+
try:
|
|
131
|
+
return parse_pull_request(remote_url + "/pull/" + pull_request)
|
|
132
|
+
except RuntimeError:
|
|
133
|
+
# Fall back on original error message
|
|
134
|
+
pass
|
|
121
135
|
raise RuntimeError("Did not understand PR argument. PR must be URL")
|
|
122
136
|
|
|
123
137
|
github_url = m.group("github_url")
|
|
@@ -57,7 +57,9 @@ def main(
|
|
|
57
57
|
# Furthermore, the parent commits of PR are ignored: we always
|
|
58
58
|
# take the canonical version of the patch from any given pr
|
|
59
59
|
|
|
60
|
-
params = ghstack.github_utils.parse_pull_request(
|
|
60
|
+
params = ghstack.github_utils.parse_pull_request(
|
|
61
|
+
pull_request, sh=sh, remote_name=remote_name
|
|
62
|
+
)
|
|
61
63
|
default_branch = ghstack.github_utils.get_github_repo_info(
|
|
62
64
|
github=github,
|
|
63
65
|
sh=sh,
|
|
@@ -341,8 +341,8 @@ class Submitter:
|
|
|
341
341
|
|
|
342
342
|
# Instead of merging into base branch, merge directly into the appropriate
|
|
343
343
|
# main or head branch. Change merge targets appropriately as PRs get
|
|
344
|
-
# merged
|
|
345
|
-
|
|
344
|
+
# merged. If None, infer whether or not the PR should be direct or not.
|
|
345
|
+
direct_opt: Optional[bool] = None
|
|
346
346
|
|
|
347
347
|
# ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
348
348
|
# Computed in post init
|
|
@@ -356,6 +356,8 @@ class Submitter:
|
|
|
356
356
|
|
|
357
357
|
base: str = dataclasses.field(init=False)
|
|
358
358
|
|
|
359
|
+
direct: bool = dataclasses.field(init=False)
|
|
360
|
+
|
|
359
361
|
# ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
360
362
|
# Mutable state; TODO: remove me
|
|
361
363
|
|
|
@@ -405,6 +407,18 @@ class Submitter:
|
|
|
405
407
|
|
|
406
408
|
object.__setattr__(self, "base", default_branch)
|
|
407
409
|
|
|
410
|
+
# Check if direct should be used, if the user didn't explicitly
|
|
411
|
+
# specify an option
|
|
412
|
+
direct = self.direct_opt
|
|
413
|
+
if direct is None:
|
|
414
|
+
direct_r = self.sh.git(
|
|
415
|
+
"cat-file", "-e", "HEAD:.github/ghstack_direct", exitcode=True
|
|
416
|
+
)
|
|
417
|
+
assert isinstance(direct_r, bool)
|
|
418
|
+
direct = direct_r
|
|
419
|
+
|
|
420
|
+
object.__setattr__(self, "direct", direct)
|
|
421
|
+
|
|
408
422
|
# ~~~~~~~~~~~~~~~~~~~~~~~~
|
|
409
423
|
# The main algorithm
|
|
410
424
|
|
|
@@ -664,7 +678,6 @@ class Submitter:
|
|
|
664
678
|
commits_to_submit: List[ghstack.git.CommitHeader],
|
|
665
679
|
commits_to_rebase: List[ghstack.git.CommitHeader],
|
|
666
680
|
) -> Tuple[Dict[GitCommitHash, DiffMeta], Dict[GitCommitHash, GitCommitHash]]:
|
|
667
|
-
|
|
668
681
|
# Prepare diffs in reverse topological order.
|
|
669
682
|
# (Reverse here is important because we must have processed parents
|
|
670
683
|
# first.)
|
|
@@ -802,7 +815,7 @@ as it supports bidirectional syncing. However, there is no way to
|
|
|
802
815
|
convert a pre-existing PR in the old style to the new format which
|
|
803
816
|
supports bidirectional syncing. If you would like to blow away the old
|
|
804
817
|
PR and start anew, edit the Summary in the Phabricator diff to delete
|
|
805
|
-
the line 'Pull
|
|
818
|
+
the line 'Pull-Request-resolved' and then run ghexport again.
|
|
806
819
|
"""
|
|
807
820
|
)
|
|
808
821
|
|
|
@@ -819,7 +832,7 @@ the Phabricator diff page? If so, please continue to use that button
|
|
|
819
832
|
to export your diff.
|
|
820
833
|
|
|
821
834
|
If you think this is in error, edit the Summary in the Phabricator diff
|
|
822
|
-
to delete the line 'Pull
|
|
835
|
+
to delete the line 'Pull-Request-resolved' and then run ghexport again.
|
|
823
836
|
"""
|
|
824
837
|
)
|
|
825
838
|
else:
|
|
@@ -950,17 +963,20 @@ to disassociate the commit with the pull request, and then try again.
|
|
|
950
963
|
commit_msg = self._update_source_id(diff.summary, elab_diff)
|
|
951
964
|
else:
|
|
952
965
|
# Need to insert metadata for the first time
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
966
|
+
# TODO: Probably quicker if we reimplement reinterpret-trailers
|
|
967
|
+
# in Python
|
|
968
|
+
commit_msg = self.sh.git(
|
|
969
|
+
"interpret-trailers",
|
|
970
|
+
"--trailer",
|
|
971
|
+
f"ghstack-source-id: {diff.source_id}",
|
|
972
|
+
*(
|
|
973
|
+
["--trailer", f"ghstack-comment-id: {elab_diff.comment_id}"]
|
|
974
|
+
if self.direct
|
|
975
|
+
else []
|
|
976
|
+
),
|
|
977
|
+
"--trailer",
|
|
978
|
+
f"Pull-Request-resolved: {pull_request_resolved.url()}",
|
|
979
|
+
input=strip_mentions(diff.summary.rstrip()),
|
|
964
980
|
)
|
|
965
981
|
|
|
966
982
|
return DiffMeta(
|
|
@@ -1463,6 +1479,30 @@ is closed (likely due to being merged). Please rebase to upstream and try again
|
|
|
1463
1479
|
push_branches: List[str] = []
|
|
1464
1480
|
force_push_branches: List[str] = []
|
|
1465
1481
|
|
|
1482
|
+
for s in reversed(diffs_to_submit):
|
|
1483
|
+
# It is VERY important that we do base updates BEFORE real
|
|
1484
|
+
# head updates, otherwise GitHub will spuriously think that
|
|
1485
|
+
# the user pushed a number of patches as part of the PR,
|
|
1486
|
+
# when actually they were just from the (new) upstream
|
|
1487
|
+
# branch
|
|
1488
|
+
|
|
1489
|
+
for diff, b in s.push_branches:
|
|
1490
|
+
if b == "orig":
|
|
1491
|
+
q = force_push_branches
|
|
1492
|
+
elif b == "base":
|
|
1493
|
+
q = base_push_branches
|
|
1494
|
+
else:
|
|
1495
|
+
q = push_branches
|
|
1496
|
+
q.append(push_spec(diff, branch(s.username, s.ghnum, b)))
|
|
1497
|
+
# Careful! Don't push master.
|
|
1498
|
+
# TODO: These pushes need to be atomic (somehow)
|
|
1499
|
+
if base_push_branches:
|
|
1500
|
+
self._git_push(base_push_branches)
|
|
1501
|
+
if push_branches:
|
|
1502
|
+
self._git_push(push_branches, force=self.force)
|
|
1503
|
+
if force_push_branches:
|
|
1504
|
+
self._git_push(force_push_branches, force=True)
|
|
1505
|
+
|
|
1466
1506
|
for s in reversed(diffs_to_submit):
|
|
1467
1507
|
# NB: GraphQL API does not support modifying PRs
|
|
1468
1508
|
assert not s.closed
|
|
@@ -1500,29 +1540,6 @@ is closed (likely due to being merged). Please rebase to upstream and try again
|
|
|
1500
1540
|
body=stack_desc,
|
|
1501
1541
|
)
|
|
1502
1542
|
|
|
1503
|
-
# It is VERY important that we do base updates BEFORE real
|
|
1504
|
-
# head updates, otherwise GitHub will spuriously think that
|
|
1505
|
-
# the user pushed a number of patches as part of the PR,
|
|
1506
|
-
# when actually they were just from the (new) upstream
|
|
1507
|
-
# branch
|
|
1508
|
-
|
|
1509
|
-
for diff, b in s.push_branches:
|
|
1510
|
-
if b == "orig":
|
|
1511
|
-
q = force_push_branches
|
|
1512
|
-
elif b == "base":
|
|
1513
|
-
q = base_push_branches
|
|
1514
|
-
else:
|
|
1515
|
-
q = push_branches
|
|
1516
|
-
q.append(push_spec(diff, branch(s.username, s.ghnum, b)))
|
|
1517
|
-
# Careful! Don't push master.
|
|
1518
|
-
# TODO: These pushes need to be atomic (somehow)
|
|
1519
|
-
if base_push_branches:
|
|
1520
|
-
self._git_push(base_push_branches)
|
|
1521
|
-
if push_branches:
|
|
1522
|
-
self._git_push(push_branches)
|
|
1523
|
-
if force_push_branches:
|
|
1524
|
-
self._git_push(force_push_branches, force=True)
|
|
1525
|
-
|
|
1526
1543
|
# Report what happened
|
|
1527
1544
|
def format_url(s: DiffMeta) -> str:
|
|
1528
1545
|
return "https://{github_url}/{owner}/{repo}/pull/{number}".format(
|
|
@@ -1784,6 +1801,7 @@ is closed (likely due to being merged). Please rebase to upstream and try again
|
|
|
1784
1801
|
self.sh.git(
|
|
1785
1802
|
"push",
|
|
1786
1803
|
self.remote_name,
|
|
1804
|
+
"--no-verify",
|
|
1787
1805
|
*(["--force"] if force else []),
|
|
1788
1806
|
*branches,
|
|
1789
1807
|
)
|
ghstack-0.9.3/LICENSE
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
Copyright (c) Edward Z. Yang <ezyang@mit.edu>
|
|
2
|
-
|
|
3
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
-
in the Software without restriction, including without limitation the rights
|
|
6
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
-
furnished to do so, subject to the following conditions:
|
|
9
|
-
|
|
10
|
-
The above copyright notice and this permission notice shall be included in all
|
|
11
|
-
copies or substantial portions of the Software.
|
|
12
|
-
|
|
13
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
-
SOFTWARE.
|
ghstack-0.9.3/ghstack/inbox.py
DELETED
ghstack-0.9.3/pyproject.toml
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "ghstack"
|
|
3
|
-
version = "0.9.3"
|
|
4
|
-
authors = ["Edward Z. Yang <ezyang@mit.edu>"]
|
|
5
|
-
description = "Stack diff support for GitHub"
|
|
6
|
-
readme = "README.md"
|
|
7
|
-
repository = "https://github.com/ezyang/ghstack"
|
|
8
|
-
include = ["ghstack/py.typed"]
|
|
9
|
-
license = "MIT"
|
|
10
|
-
classifiers = [
|
|
11
|
-
"Programming Language :: Python :: 3",
|
|
12
|
-
"License :: OSI Approved :: MIT License",
|
|
13
|
-
"Operating System :: OS Independent",
|
|
14
|
-
]
|
|
15
|
-
|
|
16
|
-
[tool.poetry.scripts]
|
|
17
|
-
ghstack = "ghstack.cli:main"
|
|
18
|
-
|
|
19
|
-
[tool.poetry.dependencies]
|
|
20
|
-
aiohttp = "^3"
|
|
21
|
-
importlib-metadata = { version = ">=1.4", python = "<3.8" }
|
|
22
|
-
python = "^3.8.1"
|
|
23
|
-
requests = "^2"
|
|
24
|
-
typing-extensions = ">=3 <5"
|
|
25
|
-
click = "^8"
|
|
26
|
-
flake8 = "^7.0.0"
|
|
27
|
-
|
|
28
|
-
[tool.poetry.dev-dependencies]
|
|
29
|
-
black = "^24.3.0"
|
|
30
|
-
flake8 = "^7"
|
|
31
|
-
graphql-core = "^3"
|
|
32
|
-
hypothesis = "^6"
|
|
33
|
-
mypy = "^1"
|
|
34
|
-
pytest = "^7"
|
|
35
|
-
usort = "^1"
|
|
36
|
-
ufmt = "^2"
|
|
37
|
-
lintrunner = "^0.11.0"
|
|
38
|
-
types-requests = "^2.31.0.10"
|
|
39
|
-
pytest-xdist = "^3.5.0"
|
|
40
|
-
expecttest = "^0.2.0"
|
|
41
|
-
|
|
42
|
-
[build-system]
|
|
43
|
-
requires = ["poetry-core>=1.0.0"]
|
|
44
|
-
build-backend = "poetry.core.masonry.api"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|