Diff
Not logged in

Differences From Artifact [de331db2a1]:

To Artifact [42f6088384]:


33
34
35
36
37
38
39












































































































































































































































































































40
41
42
43
44
45
46
  [file tail [info nameofexecutable]]\
  [file tail [info script]] \[apiKey\] \[name\] \[version\] \[language\]\
  \[fileName1\] ... \[fileNameN\]"

    exit 1
  }













































































































































































































































































































  #
  # NOTE: Figure out the fully qualified path to the current script file.
  #       If necessary, add it to the auto-path for the interpreter.  The
  #       necessary supporting packages (i.e. the Package Repository and
  #       other support packages) that are assumed to exist in the same
  #       directory as the current script file.
  #







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
  [file tail [info nameofexecutable]]\
  [file tail [info script]] \[apiKey\] \[name\] \[version\] \[language\]\
  \[fileName1\] ... \[fileNameN\]"

    exit 1
  }

  #
  # NOTE: This procedure sets up the default values for all configuration
  #       parameters used by the package uploader client.  The script
  #       argument is the fully qualified path and file name for the script
  #       being evaluated.
  #
  proc setupUploadVars { script } {
    #
    # NOTE: What is the fully qualified path to the directory containing the
    #       checkout for the package client?
    #
    variable checkoutDirectory

    if {![info exists checkoutDirectory]} then {
      set checkoutDirectory [file dirname $script]
    }

    #
    # NOTE: The command to use when attempting to stage package files using
    #       Fossil.
    #
    variable fossilAddCommand; # DEFAULT fossil add {${fileName}}

    if {![info exists fossilAddCommand]} then {
      set fossilAddCommand {fossil add {${fileName}}}
    }

    #
    # NOTE: The command to use when attempting to commit package files using
    #       Fossil.
    #
    variable fossilCommitCommand; # DEFAULT fossil commit ...

    if {![info exists fossilCommitCommand]} then {
      set fossilCommitCommand {fossil commit -m {${comment}}\
          --branch {${branch}} --user anonymous --chdir \
          {${checkoutDirectory}} --no-prompt}
    }

    #
    # NOTE: The regular expression pattern used when attempting to verify
    #       that Fossil committed a set of files.
    #
    variable fossilCommitPattern; # DEFAULT: {^New_Version: ([0-9a-f]{40})$}

    if {![info exists fossilCommitPattern]} then {
      set fossilCommitPattern {^New_Version: ([0-9a-f]{40})$}
    }
  }

  #
  # NOTE: This procedure returns a string value, formatted for use within a
  #       script block being processed by the [string map] command.  The
  #       value argument is the string value to format.  No return value is
  #       reserved to indicate an error.  This procedure may not raise any
  #       script errors.
  #
  proc formatStringMapValue { value } {
    if {[string length $value] == 0} then {
      return \"\"
    }

    set list [list $value]

    if {$value eq $list} then {
      return $value
    } else {
      return $list
    }
  }

  #
  # NOTE: This procedure processes a list of qualified file names and tries
  #       to determine their common containing directory, if any.  The
  #       fileNames argument is the list of (fully?) qualified file names to
  #       process.
  #
  proc getContainingDirectory { fileNames } {
    set result ""
    set resultParts [list]

    foreach fileName $fileNames {
      set directory [file dirname $fileName]
      set directoryParts [file split $directory]

      if {[llength $resultParts] == 0 || \
          [llength $directoryParts] < [llength $resultParts]} then {
        set result $directory
        set resultParts $directoryParts
      } elseif {[llength $directoryParts] == [llength $resultParts] && \
          $directory ne $result} then {
        set result [file dirname $directory]
        set resultParts [file split $result]
      }
    }

    return $result
  }

  #
  # NOTE: This procedure attempts to process a list of (fully?) qualified file
  #       names and return the corresponding list of relative file names.  The
  #       fileNames argument is the list of (fully?) qualified file names to
  #       process.  This procedure may raise script errors.
  #
  proc getRelativeFileNames { fileNames } {
    set directory [getContainingDirectory $fileNames]
    set directoryParts [file split $directory]
    set fileNameIndex [expr {[llength $directoryParts] - 1}]

    if {$fileNameIndex < 0} then {
      error [appendArgs \
          "invalid containing directory \"" $directory \
          "\": cannot go up one level"]
    }

    set relativeFileNames [list]

    foreach fileName $fileNames {
      set fileNameParts [lrange \
          [file split $fileName] $fileNameIndex end]

      if {$maximumLevels > 0 && \
          [llength $fileNameParts] > $maximumLevels} then {
        error [appendArgs \
            "depth for file name \"" $fileName \
            "\" exceeds maximum (" $maximumLevels )]
      }

      set relativeFileName [eval file join $fileNameParts]

      if {[string length $relativeFileName] == 0 || \
          [file pathtype $relativeFileName] ne "relative"} then {
        error [appendArgs \
            "bad file name \"" $relativeFileName "\", not relative"]
      }

      lappend relativeFileNames $relativeFileName
    }

    return $relativeFileNames
  }

  #
  # NOTE: This procedure attempts to create a script chunk that appends the
  #       specified list of file names to a list variable.  The fileNames
  #       argument is the list of (fully?) qualified file names to append to
  #       the list variable.  The maximumLevels argument is the maximum path
  #       depth allowed for all file names.  This procedure may raise script
  #       errors.
  #
  proc getScriptChunkForFileNames { fileNames maximumLevels } {
    set result ""
    set relativeFileNames [getRelativeFileNames $fileNames]

    foreach relativeFileName $relativeFileNames {
      if {[string length $result] > 0} then {
        append result \n
      }

      append result {  lappend fileNames [file join }
      append result [file split $relativeFileName]
      append result \]
    }

    return $result
  }

  #
  # NOTE: This procedure creates and returns a script block designed for use
  #       with the package repository server in order to download and provide
  #       a package consisting of a set of files.  The language argument must
  #       be the literal string "eagle" or the literal string "tcl".  The
  #       version argument must be one of the literal strings "8.4", "8.5",
  #       or "8.6" when the language is "tcl" -OR- the literal string "1.0"
  #       when the language is "eagle".  The platform argument must be an
  #       empty string -OR- one of the literal strings "neutral", "win32-arm",
  #       "win32-x86", "win64-arm64", "win64-ia64", or "win64-x64".  The
  #       fileNames argument is the list of (fully?) qualified file names to
  #       be downloaded when the associated package is being provided.  The
  #       options argument is reserved for future use, it should be an empty
  #       list.
  #
  proc createRepositoryScript { language version platform fileNames options } {
    ::PackageDownloader::verifyLanguageAndVersion $language $version isClient
    ::PackageDownloader::verifyPlatform $platform platform

    return [string trim [string map [list \r\n \n \
        %language% [formatStringMapValue $language] \
        %version% [formatStringMapValue $version] \
        %platform% [formatStringMapValue $platform] \
        %backslash% \\ %ns% ::PackageDownloader %fileNames% \
        [getScriptChunkForFileNames \
        $fileNames 2]] {
apply [list [list] {
  package require Eagle.Package.Downloader

  %ns%::resetCookieAndLoginSimple

  set fileNames [list]

%fileNames%

  set options [list %backslash%
      -persistent false -usePgp true -useAutoPath true]

  %ns%::downloadFiles %language% %version% %platform% $fileNames $options
  %ns%::logoutAndResetCookie
}]
    }]]
  }

  #
  # NOTE: This procedure attempts to stage the specified package files using
  #       Fossil.  The fileNames argument is a list of (fully?) qualified
  #       local file names to stage.
  #
  proc stagePackageFiles { language version platform fileNames } {
    variable checkoutDirectory
    variable fossilAddCommand

    set relativeFileNames [getRelativeFileNames $fileNames]
    set savedPwd [pwd]; cd $checkoutDirectory

    foreach fileName $fileNames relativeFileName $relativeFileNames {
      file mkdir [file join \
          $language $version $platform [file dirname $relativeFileName]]

      file copy $fileName $relativeFileName
      set fileName $relativeFileName

      if {[isEagle]} then {
        set fileName [::PackageRepository::formatExecArgument $fileName]

        if {[catch {
          eval exec -success Success [subst $fossilAddCommand]
        } error]} then {
          cd $savedPwd

          error [appendArgs \
              "failed to stage file \"" $fileName "\": " $error]
        }
      } else {
        if {[catch {
          eval exec [subst $fossilAddCommand]
        } error]} then {
          cd $savedPwd

          error [appendArgs \
              "failed to stage file \"" $fileName "\": " $error]
        }
      }
    }

    cd $savedPwd
  }

  #
  # NOTE: This procedure attempts to commit the staged package files to the
  #       remote package file repository using Fossil.  The varName argument
  #       is the name of a scalar variable in the context of the immediate
  #       caller that will receive the resulting Fossil check-in identifier.
  #
  proc commitPackageFiles { varName } {
    variable checkoutDirectory
    variable fossilCommitCommand
    variable fossilCommitPattern

    set branch ""; # TODO: Figure out a good branch.
    set comment ""; # TODO: Figure out a good comment.

    if {[isEagle]} then {
      if {[catch {
        eval exec -nocarriagereturns -stdout output -stderr error \
            [subst $fossilCommitCommand]
      } result] == 0} then {
        set result [appendArgs $output $error]
      } else {
        return false
      }
    } else {
      if {[catch {
        eval exec [subst $fossilCommitCommand]
      } result]} then {
        return false
      }
    }

    if {[string length $varName] > 0} then {
      upvar 1 $varName checkin
    }

    if {![info exists result] || \
        ![regexp -line -- $fossilCommitPattern $result dummy checkin]} then {
      return false
    }

    return true
  }

  #
  # NOTE: Figure out the fully qualified path to the current script file.
  #       If necessary, add it to the auto-path for the interpreter.  The
  #       necessary supporting packages (i.e. the Package Repository and
  #       other support packages) that are assumed to exist in the same
  #       directory as the current script file.
  #
63
64
65
66
67
68
69

70
71
72

























73
74
75
76
77
78
79
  #       package.
  #
  namespace eval ::PackageRepository {
    variable verboseUriDownload true
  }

  #

  # NOTE: Load the Package Repository Client package now.
  #
  package require Eagle.Package.Repository


























  #
  # NOTE: Verify that the number of command line arguments meets the basic
  #       requirements of this tool.
  #
  if {[info exists ::argv] && [llength $::argv] >= 5} then {
    #







>
|

|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
  #       package.
  #
  namespace eval ::PackageRepository {
    variable verboseUriDownload true
  }

  #
  # NOTE: This package requires both the package repository and downloader
  #       client packages.
  #
  package require Eagle.Package.Downloader

  #
  # NOTE: This package requires that support for namespaces, which is an
  #       optional feature of Eagle, must be enabled.
  #
  if {[isEagle] && ![namespace enable]} then {
    error "namespaces must be enabled for this package"
  }

  #
  # NOTE: Attempt to read optional settings file now.  This may override
  #       one or more of the variable setup in the next step.
  #
  ::PackageRepository::maybeReadSettingsFile [info script]

  #
  # NOTE: Setup the variables, within this namespace, used by this script.
  #
  setupUploadVars [info script]

  #
  # NOTE: Provide the package to the interpreter.
  #
  package provide Eagle.Package.Uploader \
    [expr {[isEagle] ? [info engine PatchLevel] : "1.0"}]

  #
  # NOTE: Verify that the number of command line arguments meets the basic
  #       requirements of this tool.
  #
  if {[info exists ::argv] && [llength $::argv] >= 5} then {
    #