@@ -168,6 +168,9 @@ def __init__(self, dbgym_workspace_path: Path):
168
168
169
169
self .base_dbgym_repo_dpath = get_base_dbgym_repo_dpath ()
170
170
self .cur_path_list : list [str ] = ["dbgym" ]
171
+ self .app_name = (
172
+ "dbgym" # TODO: discover this dynamically. app means dbgym or an agent
173
+ )
171
174
172
175
# Set and create paths.
173
176
self .dbgym_workspace_path = dbgym_workspace_path
@@ -220,6 +223,56 @@ def __init__(self, dbgym_workspace_path: Path):
220
223
try_remove_file (self .dbgym_latest_run_path )
221
224
try_create_symlink (self .dbgym_this_run_path , self .dbgym_latest_run_path )
222
225
226
+ # TODO(phw2): refactor our manual symlinking in postgres/cli.py to use link_result() instead
227
+ def link_result (
228
+ self ,
229
+ result_fordpath : Path ,
230
+ custom_result_name : Optional [str ] = None ,
231
+ ) -> Path :
232
+ """
233
+ result_fordpath must be a "result", meaning it was generated inside dbgym_workspace.dbgym_this_run_path.
234
+ Further, result_fordpath must have been generated by this invocation to task.py. This also means that
235
+ result_fordpath itself can be a file or a dir but not a symlink.
236
+ Given a file or directory in task_runs/run_*/[codebase]/[org], this will create a symlink inside
237
+ symlinks/[codebase]/[org]/.
238
+ Will override the old symlink if there is one, so that symlinks/ always contains the latest generated
239
+ version of a file.
240
+ This function will return the path to the symlink that was created.
241
+ """
242
+ assert isinstance (result_fordpath , Path )
243
+ assert is_fully_resolved (
244
+ result_fordpath
245
+ ), f"result_fordpath ({ result_fordpath } ) should be a fully resolved path"
246
+ assert is_child_path (result_fordpath , self .dbgym_this_run_path )
247
+ assert not os .path .islink (result_fordpath )
248
+
249
+ if type (custom_result_name ) is str :
250
+ result_name = custom_result_name
251
+ else :
252
+ if os .path .isfile (result_fordpath ):
253
+ result_name = basename_of_path (result_fordpath ) + ".link"
254
+ elif os .path .isdir (result_fordpath ):
255
+ result_name = basename_of_path (result_fordpath ) + ".link"
256
+ else :
257
+ raise AssertionError ("result_fordpath must be either a file or dir" )
258
+
259
+ # TODO: check that it was generated in this run_*/.
260
+ symlink_parent_dpath = self .dbgym_symlinks_path / self .app_name
261
+ symlink_parent_dpath .mkdir (parents = True , exist_ok = True )
262
+
263
+ # Remove the old symlink ("old" meaning created in an earlier run) if there is one
264
+ # Note that in a multi-threaded setting, this might remove one created by a process in the same run,
265
+ # meaning it's not "old" by our definition of "old". However, we'll always end up with a symlink
266
+ # file of the current run regardless of the order of threads.
267
+ assert result_name .endswith (".link" ) and not result_name .endswith (
268
+ ".link.link"
269
+ ), f'result_name ({ result_name } ) should end with ".link"'
270
+ symlink_path = symlink_parent_dpath / result_name
271
+ try_remove_file (symlink_path )
272
+ try_create_symlink (result_fordpath , symlink_path )
273
+
274
+ return symlink_path
275
+
223
276
# `append_group()` is used to mark the "codebase path" of an invocation of the CLI. The "codebase path" is
224
277
# explained further in the documentation.
225
278
def append_group (self , name : str ) -> None :
@@ -564,7 +617,7 @@ def save_file(dbgym_workspace: DBGymWorkspace, fpath: Path) -> None:
564
617
shutil .copy (fpath , copy_fpath )
565
618
566
619
567
- # TODO(phw2): refactor our manual symlinking in postgres/cli .py to use link_result() instead
620
+ # TODO(phw2): deprecate this once I'm done with unittest_workspace .py
568
621
def link_result (
569
622
dbgym_workspace : DBGymWorkspace ,
570
623
result_fordpath : Path ,
0 commit comments