@@ -80,7 +80,8 @@ def get_pr_info(repo: str, pr_number: int) -> dict:
8080 "--repo" ,
8181 repo ,
8282 "--json" ,
83- "headRefName,baseRefName,author,title,url,labels,mergeable,reviewDecision" ,
83+ "headRefName,baseRefName,author,title,url,labels,mergeable,reviewDecision,"
84+ "isCrossRepository" ,
8485 )
8586 return json .loads (result .stdout )
8687
@@ -113,6 +114,20 @@ def is_ghstack_pr(head_branch: str) -> bool:
113114 return bool (re .match (r"^gh/[^/]+/\d+/head$" , head_branch ))
114115
115116
117+ def reject_cross_repository_write (ctx : CommandContext , command : str ) -> bool :
118+ """Reject commands that would push through the base repository remote."""
119+ if ctx .pr_info .get ("isCrossRepository" ) is False :
120+ return False
121+ post_comment (
122+ ctx .repo ,
123+ ctx .pr_number ,
124+ f"`{ command } ` cannot safely update a branch from a fork. "
125+ "Please perform the update in the fork and push it from an account "
126+ "that controls that repository." ,
127+ )
128+ return True
129+
130+
116131def find_ghstack_stack_top (repo : str , head_branch : str ) -> int :
117132 """Return the PR number at the top of the ghstack stack containing *head_branch*.
118133
@@ -279,6 +294,9 @@ def cmd_rebase(ctx: CommandContext, args: argparse.Namespace) -> None:
279294 )
280295 return
281296
297+ if reject_cross_repository_write (ctx , "rebase" ):
298+ return
299+
282300 if is_ghstack_pr (head ):
283301 _rebase_ghstack (ctx , args )
284302 else :
@@ -380,6 +398,9 @@ def cmd_lint(ctx: CommandContext, _args: argparse.Namespace) -> None:
380398 )
381399 return
382400
401+ if reject_cross_repository_write (ctx , "lint" ):
402+ return
403+
383404 post_comment (
384405 ctx .repo ,
385406 ctx .pr_number ,
0 commit comments