@@ -23,6 +23,7 @@ import {
2323 getPatchesConfigFile ,
2424 getPatchSubjectLine ,
2525 getOctokit ,
26+ gitHashObject ,
2627 hasContentForBlobId ,
2728 parsePatchConfig ,
2829 querystringParse ,
@@ -53,6 +54,115 @@ export function registerPatchesCommands(
5354 const rootDirectory = vscode . Uri . joinPath ( electronRoot , ".." , ".." ) ;
5455
5556 context . subscriptions . push (
57+ vscode . commands . registerCommand (
58+ `${ commandPrefix } .patches.addFileToPatch` ,
59+ async ( patchTreeItem : Patch ) => {
60+ // Show text input with file picker action button
61+ const relativePath = await new Promise < string | undefined > (
62+ ( resolve ) => {
63+ const inputBox = vscode . window . createInputBox ( ) ;
64+ inputBox . title = "Add File to Patch" ;
65+ inputBox . prompt =
66+ "Enter the file path relative to the Chromium source directory" ;
67+ inputBox . placeholder = "e.g. base/logging.cc" ;
68+
69+ const browseButton : vscode . QuickInputButton = {
70+ iconPath : new vscode . ThemeIcon ( "file" ) ,
71+ tooltip : "Browse for file" ,
72+ } ;
73+ inputBox . buttons = [ browseButton ] ;
74+
75+ inputBox . onDidTriggerButton ( async ( button ) => {
76+ if ( button === browseButton ) {
77+ const [ picked ] =
78+ ( await vscode . window . showOpenDialog ( {
79+ canSelectMany : false ,
80+ defaultUri : chromiumDirectory ,
81+ openLabel : "Select file to add to patch" ,
82+ } ) ) ?? [ ] ;
83+
84+ if ( picked ) {
85+ inputBox . value = path . relative (
86+ chromiumDirectory . fsPath ,
87+ picked . fsPath ,
88+ ) ;
89+ }
90+ }
91+ } ) ;
92+
93+ inputBox . onDidChangeValue ( async ( value ) => {
94+ if ( value ) {
95+ try {
96+ const fileUri = vscode . Uri . joinPath ( chromiumDirectory , value ) ;
97+ await vscode . workspace . fs . stat ( fileUri ) ;
98+ inputBox . validationMessage = undefined ;
99+ } catch {
100+ inputBox . validationMessage = "File does not exist" ;
101+ }
102+ } else {
103+ inputBox . validationMessage = undefined ;
104+ }
105+ } ) ;
106+
107+ inputBox . onDidAccept ( async ( ) => {
108+ if ( inputBox . value ) {
109+ try {
110+ const fileUri = vscode . Uri . joinPath (
111+ chromiumDirectory ,
112+ inputBox . value ,
113+ ) ;
114+ await vscode . workspace . fs . stat ( fileUri ) ;
115+ resolve ( inputBox . value ) ;
116+ inputBox . dispose ( ) ;
117+ } catch {
118+ inputBox . validationMessage = "File does not exist" ;
119+ }
120+ }
121+ } ) ;
122+
123+ inputBox . onDidHide ( ( ) => {
124+ resolve ( undefined ) ;
125+ inputBox . dispose ( ) ;
126+ } ) ;
127+
128+ inputBox . show ( ) ;
129+ } ,
130+ ) ;
131+
132+ if ( ! relativePath ) {
133+ return ;
134+ }
135+
136+ const selectedFile = vscode . Uri . joinPath (
137+ chromiumDirectory ,
138+ relativePath ,
139+ ) ;
140+ const content = await vscode . workspace . fs
141+ . readFile ( selectedFile )
142+ . then ( ( buffer ) => buffer . toString ( ) ) ;
143+
144+ const blobId = await gitHashObject (
145+ chromiumDirectory ,
146+ Buffer . from ( content ) . toString ( "utf8" ) ,
147+ ) ;
148+
149+ const queryParams = new URLSearchParams ( ) ;
150+ queryParams . set ( "patch" , patchTreeItem . resourceUri . toString ( ) ) ;
151+ // All blobIds are the same for now since we're just loading
152+ // the file content as-is without any modifications (yet)
153+ queryParams . set ( "blobId" , blobId ) ;
154+ queryParams . set ( "blobIdA" , blobId ) ;
155+ queryParams . set ( "blobIdB" , blobId ) ;
156+
157+ const uri = selectedFile . with ( {
158+ scheme : virtualPatchFsScheme ,
159+ query : queryParams . toString ( ) ,
160+ } ) ;
161+
162+ // Open editable file which on save updates the patch
163+ return vscode . commands . executeCommand ( "vscode.open" , uri ) ;
164+ } ,
165+ ) ,
56166 vscode . commands . registerCommand (
57167 `${ commandPrefix } .patches.copyPath` ,
58168 ( patchTreeItem : Patch | FileInPatchTreeItem ) => {
0 commit comments