Sync-DJ.ps1 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. class SourceDirs {
  2. static $MixxxConfig = "$env:USERPROFILE\AppData\Local\Mixxx"
  3. static $Test = "C:\tmp\Test With Spaces"
  4. static $Desktop_ITunes = "$env:USERPROFILE\Music\iTunes\iTunes Media\Music"
  5. static $Music_MixxxConfig = "M:\Config\Mixxx"
  6. static $Music_ITunes = "M:\Music\ITUNES"
  7. static $Music_ZipDJ = "M:\Music\ZipDJ Tracks"
  8. static $Music_Music = "M:\Music"
  9. static $Drive_MixxxConfig = "D:\Config\Mixxx"
  10. static $Drive_ITunes = "D:\Music\ITUNES"
  11. static $Drive_ZipDJ = "D:\Music\ZipDJ Tracks"
  12. static $Drive_Music = "D:\Music"
  13. }
  14. class Choice {
  15. # Text to display in the option selection.
  16. [string] $DisplayName
  17. # Source diretory.
  18. [string] $Source
  19. # Destination directory.
  20. [string] $Dest
  21. # If true, rename the existing folder with a date suffix, then copy
  22. # source files to a new folder at the path.
  23. [boolean] $MakeBackup
  24. # If true, skip re-copying files if only timestamps are different.
  25. [boolean] $IgnoreTimestamps
  26. Choice($displayName, $source, $dest, $makeBackup, $ignoreTimestamps) {
  27. $this.Source = $source
  28. $this.Dest = $dest
  29. $this.DisplayName = $displayName
  30. $this.MakeBackup = $makeBackup
  31. $this.IgnoreTimestamps = $ignoreTimestamps
  32. }
  33. }
  34. $CHOICES = @(
  35. ############
  36. # Mixxx
  37. [Choice]::new(
  38. "Mixxx: Desktop --> Server",
  39. [SourceDirs]::MixxxConfig,
  40. [SourceDirs]::Music_MixxxConfig,
  41. $true, # Make Backup
  42. $false # Ignore Timestamps
  43. ),
  44. [Choice]::new(
  45. "Mixxx: Desktop --> Drive",
  46. [SourceDirs]::MixxxConfig,
  47. [SourceDirs]::Drive_MixxxConfig,
  48. $true, # Make Backup
  49. $false # Ignore Timestamps
  50. ),
  51. [Choice]::new(
  52. "Mixxx: Drive --> Laptop",
  53. [SourceDirs]::Music_MixxxConfig,
  54. [SourceDirs]::MixxxConfig,
  55. $true, # Make Backup
  56. $false # Ignore Timestamps
  57. ),
  58. [Choice]::new(
  59. "Mixxx: Drive --> Desktop",
  60. [SourceDirs]::Drive_MixxxConfig,
  61. [SourceDirs]::MixxxConfig,
  62. $true, # Make Backup
  63. $false # Ignore Timestamps
  64. ),
  65. [Choice]::new(
  66. "Mixxx: Laptop --> Drive",
  67. [SourceDirs]::MixxxConfig,
  68. [SourceDirs]::Music_MixxxConfig,
  69. $false, # Make Backup
  70. $false # Ignore Timestamps
  71. ),
  72. ##########
  73. # iTunes
  74. [Choice]::new(
  75. "iTunes: Desktop --> Server",
  76. [SourceDirs]::Desktop_ITunes,
  77. [SourceDirs]::Music_ITunes,
  78. $false, # Make Backup
  79. $true # Ignore Timestamps
  80. ),
  81. [Choice]::new(
  82. "iTunes: Drive --> Server",
  83. [SourceDirs]::Drive_ITunes,
  84. [SourceDirs]::Music_ITunes,
  85. $false, # Make Backup
  86. $true # Ignore Timestamps
  87. ),
  88. [Choice]::new(
  89. "iTunes: Server --> Desktop",
  90. [SourceDirs]::Music_ITunes,
  91. [SourceDirs]::Desktop_ITunes,
  92. $false, # Make Backup
  93. $true # Ignore Timestamps
  94. ),
  95. ##########
  96. # Music
  97. [Choice]::new(
  98. "Music: Server --> Drive",
  99. [SourceDirs]::Music_Music,
  100. [SourceDirs]::Drive_Music,
  101. $false, # Make Backup
  102. $true # Ignore Timestamps
  103. ),
  104. ##########
  105. # Zip DJ
  106. [Choice]::new(
  107. "ZipDJ: Drive --> Server",
  108. [SourceDirs]::Drive_ZipDJ,
  109. [SourceDirs]::Music_ZipDJ,
  110. $false, # Make Backup
  111. $true # Ignore Timestamps
  112. )
  113. )
  114. # Print the given message preceded by the name of the calling function.
  115. function out($message) {
  116. $caller = (Get-PSCallStack)[1].Command
  117. Write-Host "${caller}: $message"
  118. }
  119. # Print the given message, preceded by the name of the calling function,
  120. # prompt the user to hit a key, and exit.
  121. function fail($message) {
  122. $caller = (Get-PSCallStack)[1].Command
  123. Write-Host "ERROR: ${caller}: $message"
  124. Read-Host -Prompt "Press Enter to exit"
  125. exit -1
  126. }
  127. function pause($message) {
  128. $caller = (Get-PSCallStack)[1].Command
  129. Write-Host "${caller}: $message`n`n"
  130. Read-Host -Prompt "Press Enter to continue, or CTRL+C to exit"
  131. }
  132. function GetModifiedDate($dirPath) {
  133. $dir = Get-Item $dirPath
  134. $date = Get-Date $dir.LastWriteTime
  135. return $date.ToShortDateString()
  136. }
  137. # Rename the specified directory to have a suffix based on the
  138. # last modified time.
  139. function makeDatedBackup($dirPath) {
  140. if (-not(Test-Path $dirPath)) {
  141. # Not an error, but nothing we can do.
  142. return
  143. }
  144. $modifiedDate = GetModifiedDate($dirPath)
  145. $newPath = "$dirPath-$modifiedDate"
  146. if (Test-Path $newPath) {
  147. $num = 2
  148. $newNewPath = "$newPath-$num"
  149. while (Test-Path $newNewPath) {
  150. $num++
  151. $newNewPath = "$newPath-$num"
  152. }
  153. out "$newPath already exists. Using $newNewPath"
  154. $newPath = $newNewPath
  155. }
  156. $dirName = [io.path]::GetFileName($newPath)
  157. out "DEBUG: Make dated backup"
  158. pause "Moving $dirPath to $dirName"
  159. Move-Item -Path $dirPath -Destination $newPath
  160. }
  161. # Synchronize the contents of two directories.
  162. # -NoBackup: Skip moving the existing destination to a dated backup path.
  163. # -IgnoreTimestamps: Skip re-copying files if only timestamps are different.
  164. function syncDirs {
  165. param (
  166. [string] $Source,
  167. [string] $Destination,
  168. [boolean] $MakeBackup,
  169. [boolean] $IgnoreTimestamps
  170. )
  171. if (($Source.Length -eq 0) -or ($Destination.Length -eq 0)) {
  172. fail "Both Source and Destination need to be specified."
  173. }
  174. if (-not(Test-Path $Source)) {
  175. fail "Source does not exist: $Source"
  176. }
  177. if ($MakeBackup) {
  178. out "Backing up $Destination"
  179. makeDatedBackup $Destination
  180. }
  181. # Docs: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/robocopy
  182. $roboWhat = @("/s", "/copy:DAT", "/dcopy:DAT")
  183. $roboOptions = @("/v", "/j")
  184. $roboExclude = @("/xo", "/xx")
  185. $roboAdditionalExcludes = @()
  186. if ($IgnoreTimestamps) {
  187. $roboAdditionalExcludes = @("/xn")
  188. }
  189. if ($Source -eq [SourceDirs]::MixxxConfig) {
  190. $roboAdditionalExcludes = @("/xd", [string]::Format("{0}\analysis", [SourceDirs]::MixxxConfig))
  191. }
  192. pause "Copying contents of: `n`t${Source}`nTo:`n`t${Destination}"
  193. robocopy $Source $Destination $roboWhat $roboOptions $roboExclude $roboAdditionalExcludes
  194. }
  195. function chooseSyncOption() {
  196. $num = 1
  197. Write-Host "`nPick an option to run:"
  198. ForEach ($o in $CHOICES) {
  199. Write-Host ([string]::Format("{0}) {1}", $num, $o.DisplayName))
  200. $num++
  201. }
  202. Write-Host "`n`n"
  203. Write-Host "Before an event: 1, 2, 6, 9"
  204. Write-Host "During an event: 3"
  205. Write-Host "Laptop after event: 5"
  206. Write-host "After an event: 7, 8, 10, 4"
  207. $input = Read-Host -Prompt "Enter option number"
  208. $choice = [int]$input
  209. if (($choice -lt 1) -or ($choice -gt $CHOICES.Length + 1)) {
  210. fail 'Invalid choice!'
  211. }
  212. return $CHOICES[$choice-1]
  213. }
  214. function Main() {
  215. [Choice] $option = chooseSyncOption
  216. $option
  217. syncDirs `
  218. -Source $option.Source `
  219. -Destination $option.Dest `
  220. -MakeBackup $option.MakeBackup `
  221. -IgnoreTimestamps $option.IgnoreTimestamps
  222. #syncDirs -Source ([SourceDirs]::MixxxConfig) -Destination ([SourceDirs]::Test) -NoBackup -IgnoreTimestamps
  223. pause ([string]::Format(
  224. "Done running {0}!`n`t{1} --> {2}",
  225. $option.DisplayName,
  226. $option.Source,
  227. $option.Dest
  228. ))
  229. }
  230. Main