1
1
#lang racket/unit
2
2
3
3
(require "sig.rkt "
4
+ racket/list
5
+ openssl/md5
4
6
"../preferences.rkt " )
5
7
6
8
(import )
7
9
(export framework:path-utils^)
8
10
9
11
;; preferences initialized in main.rkt
10
12
13
+ (define (make-getter/ensure-exists pref-sym)
14
+ (λ ()
15
+ (let ([maybe-dir (preferences:get pref-sym)])
16
+ (and maybe-dir
17
+ (directory-exists? maybe-dir)
18
+ maybe-dir))))
19
+
11
20
(define current-backup-dir
12
- (preferences:get/set 'path-utils:backup-dir ))
21
+ (make-getter/ensure-exists 'path-utils:backup-dir ))
13
22
14
23
(define current-autosave-dir
15
- (preferences:get/set 'path-utils:autosave-dir ))
24
+ (make-getter/ensure-exists 'path-utils:autosave-dir ))
16
25
17
26
; generate-autosave-name : (or/c #f path-string? path-for-some-system?) -> path?
18
27
(define (generate-autosave-name maybe-old-path)
62
71
(if (file-exists? new-name)
63
72
(loop (add1 n))
64
73
new-name))))
65
-
74
+
75
+
76
+ ;; generate-backup-name : path? -> path?
66
77
(define (generate-backup-name full-name)
67
78
(define-values (pre-base old-name dir?)
68
79
(split-path full-name))
92
103
; we should always use a complete one.
93
104
; Using simplify-path does that and ensures no 'up or 'same
94
105
; Using ! is not completely robust, but works well enough for Emacs.
106
+ ; Windows has limitations on path lengths. Racket handles MAX_PATH
107
+ ; by using "\\?\" paths when necessary, but individual elements must
108
+ ; be shorter than lpMaximumComponentLength. If necessary, we avoid
109
+ ; this by hashing the path.
95
110
(define (encode-as-path-element base-maybe-relative name)
96
- (bytes->path-element
97
- (regexp-replace* (case (system-path-convention-type)
98
- [(windows) #rx#"\\\\ " ]
99
- [else #rx#"/ " ])
100
- (path->bytes
101
- (simplify-path (build-path base-maybe-relative name)))
102
- #"! " )))
111
+ (define windows?
112
+ (eq? 'windows (system-path-convention-type)))
113
+ (define illegal-rx
114
+ (if windows?
115
+ #rx#"\\\\ "
116
+ #rx#"/ " ))
117
+ (define pth
118
+ (simplify-path (build-path base-maybe-relative name)))
119
+ (define legible-name-bytes
120
+ (apply
121
+ bytes-append
122
+ (add-between
123
+ (for/list ([elem (in-list (explode-path pth))])
124
+ (regexp-replace* illegal-rx
125
+ (path-element->bytes elem)
126
+ #"! " ))
127
+ #"! " )))
128
+ (cond
129
+ [(or (not windows?)
130
+ (< (bytes-length legible-name-bytes)
131
+ (lpMaximumComponentLength)))
132
+ (bytes->path-element legible-name-bytes)]
133
+ [else
134
+ (string->path-element
135
+ (regexp-replace*
136
+ #rx"\\\\ " ; NOT illegal-rx : this is a string regexp
137
+ (md5 (open-input-bytes (path->bytes pth)))
138
+ "! " ))]))
139
+
140
+
141
+
142
+ ;; lpMaximumComponentLength : -> real?
143
+ ;; Returns the maximum length of an element of a "\\?\" path on Windows.
144
+ ;; For now, assuming 255, but really this should be
145
+ ;; "the value returned in the lpMaximumComponentLength parameter
146
+ ;; of the GetVolumeInformation function".
147
+ (define (lpMaximumComponentLength)
148
+ 255 )
103
149
104
150
151
+
0 commit comments