@@ -44,6 +44,15 @@ pub fn version_binary_path(version: &Version) -> PathBuf {
4444 get_bin_dir_path ( ) . join ( format ! ( "anchor-{version}" ) )
4545}
4646
47+ /// Path to the cargo binary directory, defaults to `~/.cargo/bin` if `CARGO_HOME`
48+ #[ cfg( not( test) ) ] // this prevents tests from running this function so we don't change the developer environment during tests
49+ fn cargo_bin_dir ( ) -> Option < PathBuf > {
50+ if let Ok ( cargo_home) = std:: env:: var ( "CARGO_HOME" ) {
51+ return Some ( PathBuf :: from ( cargo_home) . join ( "bin" ) ) ;
52+ }
53+ dirs:: home_dir ( ) . map ( |home| home. join ( ".cargo" ) . join ( "bin" ) )
54+ }
55+
4756/// Ensure the users home directory is setup with the paths required by AVM.
4857pub fn ensure_paths ( ) {
4958 let home_dir = AVM_HOME . to_path_buf ( ) ;
@@ -94,6 +103,73 @@ pub fn ensure_paths() {
94103 }
95104 }
96105
106+ // Try to make `anchor` available on PATH by placing it into $CARGO_HOME/bin (or ~/.cargo/bin).
107+ #[ cfg( not( test) ) ]
108+ {
109+ if let Some ( cargo_bin) = cargo_bin_dir ( ) {
110+ if cargo_bin. exists ( ) {
111+ let anchor_in_cargo = cargo_bin. join ( if cfg ! ( target_os = "windows" ) {
112+ "anchor.exe"
113+ } else {
114+ "anchor"
115+ } ) ;
116+ if !anchor_in_cargo. exists ( ) {
117+ let target = avm_in_bin. clone ( ) ; // ~/.avm/bin/avm
118+
119+ let mut linked = false ;
120+ #[ cfg( unix) ]
121+ {
122+ if let Err ( e) = std:: os:: unix:: fs:: symlink ( & target, & anchor_in_cargo) {
123+ eprintln ! (
124+ "Failed to create cargo-bin symlink: {e}. Falling back to copy."
125+ ) ;
126+ } else {
127+ linked = true ;
128+ }
129+ }
130+ #[ cfg( windows) ]
131+ {
132+ use std:: os:: windows:: fs:: symlink_file;
133+ if let Err ( e) = symlink_file ( & target, & anchor_in_cargo) {
134+ eprintln ! (
135+ "Failed to create cargo-bin symlink: {e}. Falling back to copy."
136+ ) ;
137+ } else {
138+ linked = true ;
139+ }
140+ }
141+
142+ if !linked {
143+ if let Err ( e) = fs:: copy ( & target, & anchor_in_cargo) {
144+ eprintln ! (
145+ "Failed to place `anchor` in {}: {}.\n Add {} to your PATH or create a symlink manually." ,
146+ cargo_bin. display( ) ,
147+ e,
148+ bin_dir. display( )
149+ ) ;
150+ } else {
151+ // Ensure executable bit on UNIX when copying.
152+ #[ cfg( unix) ]
153+ {
154+ use std:: os:: unix:: fs:: PermissionsExt ;
155+ if let Err ( e) = fs:: set_permissions (
156+ & anchor_in_cargo,
157+ fs:: Permissions :: from_mode ( 0o775 ) ,
158+ ) {
159+ eprintln ! (
160+ "Failed to set executable permissions on {}: {}" ,
161+ anchor_in_cargo. display( ) ,
162+ e
163+ ) ;
164+ }
165+ }
166+ }
167+ }
168+ }
169+ }
170+ }
171+ }
172+
97173 if !current_version_file_path ( ) . exists ( ) {
98174 fs:: File :: create ( current_version_file_path ( ) ) . expect ( "Could not create .version file" ) ;
99175 }
0 commit comments