From e203abb25c966ac830c21f9ed61e44a4f1b3cd3e Mon Sep 17 00:00:00 2001
From: LetterN <24603524+LetterN@users.noreply.github.com>
Date: Wed, 8 Sep 2021 09:10:28 +0800
Subject: [PATCH 01/11] generic controller update
---
code/controllers/admin.dm | 40 +++++-
code/controllers/failsafe.dm | 109 +++++++++++++---
code/controllers/globals.dm | 2 +-
code/controllers/master.dm | 116 +++++++++---------
code/controllers/subsystem.dm | 57 ++++++---
.../helper_datums/stack_end_detector.dm | 32 +++++
tgstation.dme | 1 +
7 files changed, 270 insertions(+), 87 deletions(-)
create mode 100644 code/datums/helper_datums/stack_end_detector.dm
diff --git a/code/controllers/admin.dm b/code/controllers/admin.dm
index 19fef28597..5c767ecb1b 100644
--- a/code/controllers/admin.dm
+++ b/code/controllers/admin.dm
@@ -1,14 +1,25 @@
// Clickable stat() button.
/obj/effect/statclick
name = "Initializing..."
+ // blocks_emissive = NONE
var/target
INITIALIZE_IMMEDIATE(/obj/effect/statclick)
-/obj/effect/statclick/Initialize(mapload, text, target) //Don't port this to Initialize it's too critical
+/obj/effect/statclick/Initialize(mapload, text, target)
. = ..()
name = text
src.target = target
+ if(istype(target, /datum)) //Harddel man bad
+ RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/cleanup)
+
+/obj/effect/statclick/Destroy()
+ target = null
+ return ..()
+
+/obj/effect/statclick/proc/cleanup()
+ SIGNAL_HANDLER
+ qdel(src)
/obj/effect/statclick/proc/update(text)
name = text
@@ -51,3 +62,30 @@ INITIALIZE_IMMEDIATE(/obj/effect/statclick)
SSblackbox.record_feedback("tally", "admin_verb", 1, "Restart Failsafe Controller")
message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
+
+/client/proc/debug_controller()
+ set category = "Debug"
+ set name = "Debug Controller"
+ set desc = "Debug the various periodic loop controllers for the game (be careful!)"
+
+ if(!holder)
+ return
+
+ var/list/controllers = list()
+ var/list/controller_choices = list()
+
+ for (var/datum/controller/controller in world)
+ if (istype(controller, /datum/controller/subsystem))
+ continue
+ controllers["[controller] (controller.type)"] = controller //we use an associated list to ensure clients can't hold references to controllers
+ controller_choices += "[controller] (controller.type)"
+
+ var/datum/controller/controller_string = input("Select controller to debug", "Debug Controller") as null|anything in controller_choices
+ var/datum/controller/controller = controllers[controller_string]
+
+ if (!istype(controller))
+ return
+ debug_variables(controller)
+
+ SSblackbox.record_feedback("tally", "admin_verb", 1, "Restart Failsafe Controller")
+ message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
diff --git a/code/controllers/failsafe.dm b/code/controllers/failsafe.dm
index a15056e442..04b88eb3be 100644
--- a/code/controllers/failsafe.dm
+++ b/code/controllers/failsafe.dm
@@ -15,7 +15,7 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
// The alert level. For every failed poke, we drop a DEFCON level. Once we hit DEFCON 1, restart the MC.
var/defcon = 5
//the world.time of the last check, so the mc can restart US if we hang.
- // (Real friends look out for *eachother*)
+ // (Real friends look out for *eachother*)
var/lasttick = 0
// Track the MC iteration to make sure its still on track.
@@ -33,6 +33,22 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
/datum/controller/failsafe/Initialize()
set waitfor = FALSE
Failsafe.Loop()
+ if (!Master || defcon == 0) //Master is gone/not responding and Failsafe just exited its loop
+ defcon = 3 //Reset defcon level as its used inside the emergency loop
+ while (defcon > 0)
+ var/recovery_result = emergency_loop()
+ if (recovery_result == 1) //Exit emergency loop and delete self if it was able to recover MC
+ break
+ else if (defcon == 1) //Exit Failsafe if we weren't able to recover the MC in the last stage
+ log_game("FailSafe: Failed to recover MC while in emergency state. Failsafe exiting.")
+ message_admins(span_boldannounce("Failsafe failed criticaly while trying to recreate broken MC. Please manually fix the MC or reboot the server. Failsafe exiting now."))
+ message_admins(span_boldannounce("You can try manually calling these two procs:."))
+ message_admins(span_boldannounce("/proc/recover_all_SS_and_recreate_master: Most stuff should still function but expect instability/runtimes/broken stuff."))
+ message_admins(span_boldannounce("/proc/delete_all_SS_and_recreate_master: Most stuff will be broken but basic stuff like movement and chat should still work."))
+ else if (recovery_result == -1) //Failed to recreate MC
+ defcon--
+ sleep(initial(processing_interval)) //Wait a bit until the next try
+
if(!QDELETED(src))
qdel(src) //when Loop() returns, we delete ourselves and let the mc recreate us
@@ -45,42 +61,56 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
while(running)
lasttick = world.time
if(!Master)
- // Replace the missing Master! This should never, ever happen.
- new /datum/controller/master()
+ // Break out of the main loop so we go into emergency state
+ break
// Only poke it if overrides are not in effect.
if(processing_interval > 0)
if(Master.processing && Master.iteration)
+ if (defcon > 1 && (!Master.stack_end_detector || !Master.stack_end_detector.check()))
+
+ to_chat(GLOB.admins, span_boldannounce("ERROR: The Master Controller code stack has exited unexpectedly, Restarting..."))
+ defcon = 0
+ var/rtn = Recreate_MC()
+ if(rtn > 0)
+ master_iteration = 0
+ to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
+ else if(rtn < 0)
+ log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
+ to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
// Check if processing is done yet.
if(Master.iteration == master_iteration)
switch(defcon)
if(4,5)
--defcon
- if(3)
- message_admins("Notice: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks.")
- --defcon
- if(2)
- to_chat(GLOB.admins, "Warning: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks.")
- --defcon
- if(1)
- to_chat(GLOB.admins, "Warning: DEFCON [defcon_pretty()]. The Master Controller has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting...")
+ if(3)
+ message_admins(span_adminnotice("Notice: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks."))
+ --defcon
+
+ if(2)
+ to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has not fired in the last [(5-defcon) * processing_interval] ticks. Automatic restart in [processing_interval] ticks."))
+ --defcon
+
+ if(1)
+ to_chat(GLOB.admins, span_boldannounce("Warning: DEFCON [defcon_pretty()]. The Master Controller has still not fired within the last [(5-defcon) * processing_interval] ticks. Killing and restarting..."))
--defcon
var/rtn = Recreate_MC()
if(rtn > 0)
defcon = 4
master_iteration = 0
- to_chat(GLOB.admins, "MC restarted successfully")
+ to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
else if(rtn < 0)
log_game("FailSafe: Could not restart MC, runtime encountered. Entering defcon 0")
- to_chat(GLOB.admins, "ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying.")
+ to_chat(GLOB.admins, span_boldannounce("ERROR: DEFCON [defcon_pretty()]. Could not restart MC, runtime encountered. I will silently keep retrying."))
//if the return number was 0, it just means the mc was restarted too recently, and it just needs some time before we try again
//no need to handle that specially when defcon 0 can handle it
+
if(0) //DEFCON 0! (mc failed to restart)
var/rtn = Recreate_MC()
if(rtn > 0)
defcon = 4
master_iteration = 0
- to_chat(GLOB.admins, "MC restarted successfully")
+ to_chat(GLOB.admins, span_adminnotice("MC restarted successfully"))
else
defcon = min(defcon + 1,5)
master_iteration = Master.iteration
@@ -92,6 +122,57 @@ GLOBAL_REAL(Failsafe, /datum/controller/failsafe)
defcon = 5
sleep(initial(processing_interval))
+//Emergency loop used when Master got deleted or the main loop exited while Defcon == 0
+//Loop is driven externally so runtimes only cancel the current recovery attempt
+/datum/controller/failsafe/proc/emergency_loop()
+ //The code in this proc should be kept as simple as possible, anything complicated like to_chat might rely on master existing and runtime
+ //The goal should always be to get a new Master up and running before anything else
+ . = -1
+ switch (defcon) //The lower defcon goes the harder we try to fix the MC
+ if (2 to 3) //Try to normally recreate the MC two times
+ . = Recreate_MC()
+ if (1) //Delete the old MC first so we don't transfer any info, in case that caused any issues
+ del(Master)
+ . = Recreate_MC()
+
+ if (. == 1) //We were able to create a new master
+ master_iteration = 0
+ SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, span_adminnotice("Failsafe recovered MC while in emergency state [defcon_pretty()]"))
+ else
+ log_game("FailSafe: Failsafe in emergency state and was unable to recreate MC while in defcon state [defcon_pretty()].")
+ message_admins(span_boldannounce("Failsafe in emergency state and master down, trying to recreate MC while in defcon level [defcon_pretty()] failed."))
+
+///Recreate all SSs which will still cause data survive due to Recover(), the new Master will then find and take them from global.vars
+/proc/recover_all_SS_and_recreate_master()
+ del(Master)
+ var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
+ sortTim(subsytem_types, /proc/cmp_subsystem_init)
+ for(var/I in subsytem_types)
+ new I
+ . = Recreate_MC()
+ if (. == 1) //We were able to create a new master
+ SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after recovering all subsystems!"))
+ else
+ message_admins(span_boldannounce("Failed to create new MC!"))
+
+///Delete all existing SS to basically start over
+/proc/delete_all_SS_and_recreate_master()
+ del(Master)
+ for(var/global_var in global.vars)
+ if (istype(global.vars[global_var], /datum/controller/subsystem))
+ del(global.vars[global_var])
+ . = Recreate_MC()
+ if (. == 1) //We were able to create a new master
+ SSticker.Recover(); //Recover the ticket system so the Masters runlevel gets set
+ Master.Initialize(10, FALSE, TRUE) //Need to manually start the MC, normally world.new would do this
+ to_chat(GLOB.admins, span_adminnotice("MC successfully recreated after deleting and recreating all subsystems!"))
+ else
+ message_admins(span_boldannounce("Failed to create new MC!"))
+
/datum/controller/failsafe/proc/defcon_pretty()
return defcon
diff --git a/code/controllers/globals.dm b/code/controllers/globals.dm
index 21f022acfd..7b5cc94d36 100644
--- a/code/controllers/globals.dm
+++ b/code/controllers/globals.dm
@@ -14,7 +14,7 @@ GLOBAL_REAL(GLOB, /datum/controller/global_vars)
var/datum/controller/exclude_these = new
gvars_datum_in_built_vars = exclude_these.vars + list(NAMEOF(src, gvars_datum_protected_varlist), NAMEOF(src, gvars_datum_in_built_vars), NAMEOF(src, gvars_datum_init_order))
- QDEL_IN(exclude_these, 0) //signal logging isn't ready
+ QDEL_IN(exclude_these, 0) //signal logging isn't ready
log_world("[vars.len - gvars_datum_in_built_vars.len] global variables")
diff --git a/code/controllers/master.dm b/code/controllers/master.dm
index 59ac68960c..055271fd86 100644
--- a/code/controllers/master.dm
+++ b/code/controllers/master.dm
@@ -18,15 +18,17 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
/datum/controller/master
name = "Master"
- // Are we processing (higher values increase the processing delay by n ticks)
+ /// Are we processing (higher values increase the processing delay by n ticks)
var/processing = TRUE
- // How many times have we ran
+ /// How many times have we ran
var/iteration = 0
+ /// Stack end detector to detect stack overflows that kill the mc's main loop
+ var/datum/stack_end_detector/stack_end_detector
- // world.time of last fire, for tracking lag outside of the mc
+ /// world.time of last fire, for tracking lag outside of the mc
var/last_run
- // List of subsystems to process().
+ /// List of subsystems to process().
var/list/subsystems
// Vars for keeping track of tick drift.
@@ -34,25 +36,27 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/init_time
var/tickdrift = 0
+ /// How long is the MC sleeping between runs, read only (set by Loop() based off of anti-tick-contention heuristics)
var/sleep_delta = 1
- ///Only run ticker subsystems for the next n ticks.
+ /// Only run ticker subsystems for the next n ticks.
var/skip_ticks = 0
+ /// makes the mc main loop runtime
var/make_runtime = FALSE
- var/initializations_finished_with_no_players_logged_in //I wonder what this could be?
+ var/initializations_finished_with_no_players_logged_in //I wonder what this could be?
- // The type of the last subsystem to be process()'d.
+ /// The type of the last subsystem to be fire()'d.
var/last_type_processed
- var/datum/controller/subsystem/queue_head //Start of queue linked list
- var/datum/controller/subsystem/queue_tail //End of queue linked list (used for appending to the list)
+ var/datum/controller/subsystem/queue_head //!Start of queue linked list
+ var/datum/controller/subsystem/queue_tail //!End of queue linked list (used for appending to the list)
var/queue_priority_count = 0 //Running total so that we don't have to loop thru the queue each run to split up the tick
var/queue_priority_count_bg = 0 //Same, but for background subsystems
- var/map_loading = FALSE //Are we loading in a new map?
+ var/map_loading = FALSE //!Are we loading in a new map?
- var/current_runlevel //for scheduling different subsystems for different stages of the round
+ var/current_runlevel //!for scheduling different subsystems for different stages of the round
var/sleep_offline_after_initializations = TRUE
var/static/restart_clear = 0
@@ -61,8 +65,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/static/random_seed
- //current tick limit, assigned before running a subsystem.
- //used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits
+ ///current tick limit, assigned before running a subsystem.
+ ///used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits
var/static/current_ticklimit = TICK_LIMIT_RUNNING
/datum/controller/master/New()
@@ -81,15 +85,27 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/list/_subsystems = list()
subsystems = _subsystems
if (Master != src)
- if (istype(Master))
+ if (istype(Master)) //If there is an existing MC take over his stuff and delete it
Recover()
qdel(Master)
+ Master = src
else
+ //Code used for first master on game boot or if existing master got deleted
+ Master = src
var/list/subsytem_types = subtypesof(/datum/controller/subsystem)
sortTim(subsytem_types, /proc/cmp_subsystem_init)
+ //Find any abandoned subsystem from the previous master (if there was any)
+ var/list/existing_subsystems = list()
+ for(var/global_var in global.vars)
+ if (istype(global.vars[global_var], /datum/controller/subsystem))
+ existing_subsystems += global.vars[global_var]
+ //Either init a new SS or if an existing one was found use that
for(var/I in subsytem_types)
- _subsystems += new I
- Master = src
+ var/datum/controller/subsystem/existing_subsystem = locate(I) in existing_subsystems
+ if (istype(existing_subsystem))
+ _subsystems += existing_subsystem
+ else
+ _subsystems += new I
if(!GLOB)
new /datum/controller/global_vars
@@ -109,7 +125,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
log_world("Shutdown complete")
// Returns 1 if we created a new mc, 0 if we couldn't due to a recent restart,
-// -1 if we encountered a runtime trying to recreate it
+// -1 if we encountered a runtime trying to recreate it
/proc/Recreate_MC()
. = -1 //so if we runtime, things know we failed
if (world.time < Master.restart_timeout)
@@ -120,7 +136,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/delay = 50 * ++Master.restart_count
Master.restart_timeout = world.time + delay
Master.restart_clear = world.time + (delay * 2)
- Master.processing = FALSE //stop ticking this one
+ if (Master) //Can only do this if master hasn't been deleted
+ Master.processing = FALSE //stop ticking this one
try
new/datum/controller/master()
catch
@@ -156,22 +173,22 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
msg = "The [BadBoy.name] subsystem seems to be destabilizing the MC and will be offlined."
BadBoy.flags |= SS_NO_FIRE
if(msg)
- to_chat(GLOB.admins, "[msg]")
+ to_chat(GLOB.admins, span_boldannounce("[msg]"))
log_world(msg)
if (istype(Master.subsystems))
if(FireHim)
- Master.subsystems += new BadBoy.type //NEW_SS_GLOBAL will remove the old one
+ Master.subsystems += new BadBoy.type //NEW_SS_GLOBAL will remove the old one
subsystems = Master.subsystems
current_runlevel = Master.current_runlevel
StartProcessing(10)
else
- to_chat(world, "The Master Controller is having some issues, we will need to re-initialize EVERYTHING")
+ to_chat(world, span_boldannounce("The Master Controller is having some issues, we will need to re-initialize EVERYTHING"))
Initialize(20, TRUE)
// Please don't stuff random bullshit here,
-// Make a subsystem, give it the SS_NO_FIRE flag, and do your work in it's Initialize()
+// Make a subsystem, give it the SS_NO_FIRE flag, and do your work in it's Initialize()
/datum/controller/master/Initialize(delay, init_sss, tgs_prime)
set waitfor = 0
@@ -181,7 +198,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
if(init_sss)
init_subtypes(/datum/controller/subsystem, subsystems)
- to_chat(world, "Initializing subsystems...")
+ to_chat(world, span_boldannounce("Initializing subsystems..."))
// Sort subsystems by init_order, so they initialize in the correct order.
sortTim(subsystems, /proc/cmp_subsystem_init)
@@ -190,7 +207,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
// Initialize subsystems.
current_ticklimit = CONFIG_GET(number/tick_limit_mc_init)
for (var/datum/controller/subsystem/SS in subsystems)
- if (SS.flags & SS_NO_INIT)
+ if (SS.flags & SS_NO_INIT || SS.initialized) //Don't init SSs with the correspondig flag or if they already are initialzized
continue
SS.Initialize(REALTIMEOFDAY)
CHECK_TICK
@@ -198,7 +215,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "Initializations complete within [time] second[time == 1 ? "" : "s"]!"
- to_chat(world, "[msg]")
+ to_chat(world, span_boldannounce("[msg]"))
log_world(msg)
if (!current_runlevel)
@@ -255,11 +272,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
/datum/controller/master/proc/Loop()
. = -1
//Prep the loop (most of this is because we want MC restarts to reset as much state as we can, and because
- // local vars rock
+ // local vars rock
//all this shit is here so that flag edits can be refreshed by restarting the MC. (and for speed)
var/list/tickersubsystems = list()
- var/list/runlevel_sorted_subsystems = list(list()) //ensure we always have at least one runlevel
+ var/list/runlevel_sorted_subsystems = list(list()) //ensure we always have at least one runlevel
var/timer = world.time
for (var/thing in subsystems)
var/datum/controller/subsystem/SS = thing
@@ -305,8 +322,12 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/error_level = 0
var/sleep_delta = 1
var/list/subsystems_to_check
- //the actual loop.
+ //setup the stack overflow detector
+ stack_end_detector = new()
+ var/datum/stack_canary/canary = stack_end_detector.prime_canary()
+ canary.use_variable()
+ //the actual loop.
while (1)
tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag)))
var/starting_tick_usage = TICK_USAGE
@@ -317,7 +338,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
//Anti-tick-contention heuristics:
//if there are mutiple sleeping procs running before us hogging the cpu, we have to run later.
- // (because sleeps are processed in the order received, longer sleeps are more likely to run first)
+ // (because sleeps are processed in the order received, longer sleeps are more likely to run first)
if (starting_tick_usage > TICK_LIMIT_MC) //if there isn't enough time to bother doing anything this tick, sleep a bit.
sleep_delta *= 2
current_ticklimit = TICK_LIMIT_RUNNING * 0.5
@@ -423,6 +444,10 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
continue
if ((SS_flags & (SS_TICKER|SS_KEEP_TIMING)) == SS_KEEP_TIMING && SS.last_fire + (SS.wait * 0.75) > world.time)
continue
+ if (SS.postponed_fires >= 1)
+ SS.postponed_fires--
+ SS.update_nextfire()
+ continue
SS.enqueue()
. = 1
@@ -439,12 +464,11 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
var/tick_precentage
var/tick_remaining
var/ran = TRUE //this is right
- var/ran_non_ticker = FALSE
var/bg_calc //have we swtiched current_tick_budget to background mode yet?
var/tick_usage
//keep running while we have stuff to run and we haven't gone over a tick
- // this is so subsystems paused eariler can use tick time that later subsystems never used
+ // this is so subsystems paused eariler can use tick time that later subsystems never used
while (ran && queue_head && TICK_USAGE < TICK_LIMIT_MC)
ran = FALSE
bg_calc = FALSE
@@ -459,20 +483,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
if (!(queue_node_flags & SS_TICKER) && skip_ticks)
queue_node = queue_node.queue_next
continue
- //super special case, subsystems where we can't make them pause mid way through
- //if we can't run them this tick (without going over a tick)
- //we bump up their priority and attempt to run them next tick
- //(unless we haven't even ran anything this tick, since its unlikely they will ever be able run
- // in those cases, so we just let them run)
- if (queue_node_flags & SS_NO_TICK_CHECK)
- if (queue_node.tick_usage > TICK_LIMIT_RUNNING - TICK_USAGE && ran_non_ticker)
- if (!(queue_node_flags & SS_BACKGROUND))
- queue_node.queued_priority += queue_priority_count * 0.1
- queue_priority_count -= queue_node_priority
- queue_priority_count += queue_node.queued_priority
- current_tick_budget -= queue_node_priority
- queue_node = queue_node.queue_next
- continue
if (!bg_calc && (queue_node_flags & SS_BACKGROUND))
current_tick_budget = queue_priority_count_bg
@@ -481,7 +491,8 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
tick_remaining = TICK_LIMIT_RUNNING - TICK_USAGE
if (current_tick_budget > 0 && queue_node_priority > 0)
- tick_precentage = tick_remaining / (current_tick_budget / queue_node_priority)
+ //Give the subsystem a precentage of the remaining tick based on the remaning priority
+ tick_precentage = tick_remaining * (queue_node_priority / current_tick_budget)
else
tick_precentage = tick_remaining
@@ -489,8 +500,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
current_ticklimit = round(TICK_USAGE + tick_precentage)
- if (!(queue_node_flags & SS_TICKER))
- ran_non_ticker = TRUE
ran = TRUE
queue_node_paused = (queue_node.state == SS_PAUSED || queue_node.state == SS_PAUSING)
@@ -535,14 +544,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
queue_node.last_fire = world.time
queue_node.times_fired++
- if (queue_node_flags & SS_TICKER)
- queue_node.next_fire = world.time + (world.tick_lag * queue_node.wait)
- else if (queue_node_flags & SS_POST_FIRE_TIMING)
- queue_node.next_fire = world.time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100))
- else if (queue_node_flags & SS_KEEP_TIMING)
- queue_node.next_fire += queue_node.wait
- else
- queue_node.next_fire = queue_node.queued_time + queue_node.wait + (world.tick_lag * (queue_node.tick_overrun/100))
+ queue_node.update_nextfire()
queue_node.queued_time = 0
@@ -554,7 +556,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
. = 1
//resets the queue, and all subsystems, while filtering out the subsystem lists
-// called if any mc's queue procs runtime or exit improperly.
+// called if any mc's queue procs runtime or exit improperly.
/datum/controller/master/proc/SoftReset(list/ticker_SS, list/runlevel_SS)
. = 0
log_world("MC: SoftReset called, resetting MC queue state.")
diff --git a/code/controllers/subsystem.dm b/code/controllers/subsystem.dm
index 12798f3863..db780ca05b 100644
--- a/code/controllers/subsystem.dm
+++ b/code/controllers/subsystem.dm
@@ -29,11 +29,11 @@
var/initialized = FALSE
/// Set to 0 to prevent fire() calls, mostly for admin use or subsystems that may be resumed later
- /// use the [SS_NO_FIRE] flag instead for systems that never fire to keep it from even being added to list that is checked every tick
+ /// use the [SS_NO_FIRE] flag instead for systems that never fire to keep it from even being added to list that is checked every tick
var/can_fire = TRUE
///Bitmap of what game states can this subsystem fire at. See [RUNLEVELS_DEFAULT] for more details.
- var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire
+ var/runlevels = RUNLEVELS_DEFAULT //points of the game at which the SS can fire
/*
* The following variables are managed by the MC and should not be modified directly.
@@ -69,6 +69,9 @@
/// Tracks the amount of completed runs for the subsystem
var/times_fired = 0
+ /// How many fires have we been requested to postpone
+ var/postponed_fires = 0
+
/// Time the subsystem entered the queue, (for timing and priority reasons)
var/queued_time = 0
@@ -122,12 +125,38 @@
dequeue()
can_fire = 0
flags |= SS_NO_FIRE
- Master.subsystems -= src
+ if (Master)
+ Master.subsystems -= src
return ..()
+
+/** Update next_fire for the next run.
+ * reset_time (bool) - Ignore things that would normally alter the next fire, like tick_overrun, and last_fire. (also resets postpone)
+ */
+/datum/controller/subsystem/proc/update_nextfire(reset_time = FALSE)
+ var/queue_node_flags = flags
+
+ if (reset_time)
+ postponed_fires = 0
+ if (queue_node_flags & SS_TICKER)
+ next_fire = world.time + (world.tick_lag * wait)
+ else
+ next_fire = world.time + wait
+ return
+
+ if (queue_node_flags & SS_TICKER)
+ next_fire = world.time + (world.tick_lag * wait)
+ else if (queue_node_flags & SS_POST_FIRE_TIMING)
+ next_fire = world.time + wait + (world.tick_lag * (tick_overrun/100))
+ else if (queue_node_flags & SS_KEEP_TIMING)
+ next_fire += wait
+ else
+ next_fire = queued_time + wait + (world.tick_lag * (tick_overrun/100))
+
+
//Queue it to run.
-// (we loop thru a linked list until we get to the end or find the right point)
-// (this lets us sort our run order correctly without having to re-sort the entire already sorted list)
+// (we loop thru a linked list until we get to the end or find the right point)
+// (this lets us sort our run order correctly without having to re-sort the entire already sorted list)
/datum/controller/subsystem/proc/enqueue()
var/SS_priority = priority
var/SS_flags = flags
@@ -191,9 +220,9 @@
queue_next.queue_prev = queue_prev
if (queue_prev)
queue_prev.queue_next = queue_next
- if (src == Master.queue_tail)
+ if (Master && (src == Master.queue_tail))
Master.queue_tail = queue_prev
- if (src == Master.queue_head)
+ if (Master && (src == Master.queue_head))
Master.queue_head = queue_next
queued_time = 0
if (state == SS_QUEUED)
@@ -217,10 +246,11 @@
//used to initialize the subsystem AFTER the map has loaded
/datum/controller/subsystem/Initialize(start_timeofday)
initialized = TRUE
+ // SEND_SIGNAL(src, COMSIG_SUBSYSTEM_POST_INITIALIZE, start_timeofday)
var/time = (REALTIMEOFDAY - start_timeofday) / 10
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
- to_chat(world, "[msg]")
- log_subsystem("INIT", msg)
+ to_chat(world, span_boldannounce("[msg]"))
+ log_subsystem(msg)
return time
/datum/controller/subsystem/stat_entry(msg)
@@ -243,11 +273,10 @@
if (SS_IDLE)
. = " "
-//could be used to postpone a costly subsystem for (default one) var/cycles, cycles
-//for instance, during cpu intensive operations like explosions
+/// Causes the next "cycle" fires to be missed. Effect is accumulative but can reset by calling update_nextfire(reset_time = TRUE)
/datum/controller/subsystem/proc/postpone(cycles = 1)
- if(next_fire - world.time < wait)
- next_fire += (wait*cycles)
+ if (can_fire && cycles >= 1)
+ postponed_fires += cycles
//usually called via datum/controller/subsystem/New() when replacing a subsystem (i.e. due to a recurring crash)
//should attempt to salvage what it can from the old instance of subsystem
@@ -258,7 +287,7 @@
if (NAMEOF(src, can_fire))
//this is so the subsystem doesn't rapid fire to make up missed ticks causing more lag
if (var_value)
- next_fire = world.time + wait
+ update_nextfire(reset_time = TRUE)
if (NAMEOF(src, queued_priority)) //editing this breaks things.
return FALSE
. = ..()
diff --git a/code/datums/helper_datums/stack_end_detector.dm b/code/datums/helper_datums/stack_end_detector.dm
new file mode 100644
index 0000000000..0d621f51b3
--- /dev/null
+++ b/code/datums/helper_datums/stack_end_detector.dm
@@ -0,0 +1,32 @@
+/**
+ Stack End Detector.
+ Can detect if a given code stack has exited, used by the mc for stack overflow detection.
+
+ **/
+/datum/stack_end_detector
+ var/datum/weakref/_WF
+ var/datum/stack_canary/_canary
+
+/datum/stack_end_detector/New()
+ _canary = new()
+ _WF = WEAKREF(_canary)
+
+/** Prime the stack overflow detector.
+ Store the return value of this proc call in a proc level var.
+ Can only be called once.
+**/
+/datum/stack_end_detector/proc/prime_canary()
+ if (!_canary)
+ CRASH("Prime_canary called twice")
+ . = _canary
+ _canary = null
+
+/// Returns true if the stack is still going. Calling before the canary has been primed also returns true
+/datum/stack_end_detector/proc/check()
+ return !!_WF.resolve()
+
+/// Stack canary. Will go away if the stack it was primed by is ended by byond for return or stack overflow reasons.
+/datum/stack_canary
+
+/// empty proc to avoid warnings about unused variables. Call this proc on your canary in the stack it's watching.
+/datum/stack_canary/proc/use_variable()
diff --git a/tgstation.dme b/tgstation.dme
index c3a1e7087c..f483bcbbad 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -665,6 +665,7 @@
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"
#include "code\datums\helper_datums\icon_snapshot.dm"
+#include "code\datums\helper_datums\stack_end_detector.dm"
#include "code\datums\helper_datums\teleport.dm"
#include "code\datums\looping_sounds\_looping_sound.dm"
#include "code\datums\looping_sounds\item_sounds.dm"
From 44b9e1439171adc24099d287686baaaccc2292a7 Mon Sep 17 00:00:00 2001
From: LetterN <24603524+LetterN@users.noreply.github.com>
Date: Wed, 8 Sep 2021 09:13:14 +0800
Subject: [PATCH 02/11] cbt => juke
---
.gitignore | 76 +-
Build.bat | 5 +-
CLEAN.bat | 3 +
RUN_SERVER.bat | 3 +
tools/build/README.md | 10 +
tools/build/binaries/README.md | 1 -
tools/build/build | 2 -
tools/build/build.bat | 3 +-
tools/build/build.js | 468 +--
tools/build/build.sh | 75 -
tools/build/cbt/fs.js | 135 -
tools/build/cbt/glob.js | 3281 ------------------
tools/build/cbt/process.js | 102 -
tools/build/cbt/task.js | 107 -
tools/build/juke/index.d.ts | 248 ++
tools/build/juke/index.js | 5128 ++++++++++++++++++++++++++++
tools/build/juke/package.json | 4 +
tools/build/lib/byond.js | 115 +
tools/build/{cbt => lib}/winreg.js | 12 +-
tools/build/lib/yarn.js | 13 +
tools/build/package.json | 4 +
21 files changed, 5822 insertions(+), 3973 deletions(-)
create mode 100644 CLEAN.bat
create mode 100644 RUN_SERVER.bat
delete mode 100644 tools/build/binaries/README.md
delete mode 100755 tools/build/build.sh
delete mode 100644 tools/build/cbt/fs.js
delete mode 100644 tools/build/cbt/glob.js
delete mode 100644 tools/build/cbt/process.js
delete mode 100644 tools/build/cbt/task.js
create mode 100644 tools/build/juke/index.d.ts
create mode 100644 tools/build/juke/index.js
create mode 100644 tools/build/juke/package.json
create mode 100644 tools/build/lib/byond.js
rename tools/build/{cbt => lib}/winreg.js (81%)
create mode 100644 tools/build/lib/yarn.js
create mode 100644 tools/build/package.json
diff --git a/.gitignore b/.gitignore
index 91a0ef08eb..56a447fdd1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,14 +7,16 @@
#Ignore byond config folder.
/cfg/**/*
-#Ignore rust-g and auxmos libraries which are compiled with scripts
-*.so
-/tools/build/binaries/**/*
+# Ignore compiled linux libs in the root folder, e.g. librust_g.so
+/*.so
#Ignore compiled files and other files generated during compilation.
*.mdme
+*.mdme.*
*.dmb
*.rsc
+*.m.dme
+*.test.dme
*.lk
*.int
*.backup
@@ -53,27 +55,6 @@ __pycache__/
*.py[cod]
*$py.class
-# C extensions
-#*.so
-
-# Distribution / packaging
-.Python
-env/
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-*.egg-info/
-.installed.cfg
-*.egg
-
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
@@ -81,8 +62,7 @@ var/
*.spec
# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
+pip-*.txt
# Unit test / coverage reports
htmlcov/
@@ -92,7 +72,6 @@ htmlcov/
.cache
nosetests.xml
coverage.xml
-*,cover
.hypothesis/
# Translations
@@ -101,10 +80,6 @@ coverage.xml
# Django stuff:
*.log
-local_settings.py
-
-# Flask instance folder
-instance/
# Scrapy stuff:
.scrapy
@@ -112,9 +87,6 @@ instance/
# Sphinx documentation
docs/_build/
-# PyBuilder
-target/
-
# IPython Notebook
.ipynb_checkpoints
@@ -127,10 +99,6 @@ celerybeat-schedule
# dotenv
.env
-# virtualenv
-venv/
-ENV/
-
# IntelliJ IDEA / PyCharm (with plugin)
.idea
@@ -153,12 +121,6 @@ Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
-# Windows Installer files
-#*.cab
-#*.msi
-#*.msm
-#*.msp
-
# Windows shortcuts
*.lnk
@@ -199,11 +161,10 @@ Temporary Items
#Visual studio stuff
*.vscode/*
-!/.vscode/extensions.json
-tools/MapAtmosFixer/MapAtmosFixer/obj/*
-tools/MapAtmosFixer/MapAtmosFixer/bin/*
-tools/CreditsTool/bin/*
-tools/CreditsTool/obj/*
+/tools/MapAtmosFixer/MapAtmosFixer/obj/*
+/tools/MapAtmosFixer/MapAtmosFixer/bin/*
+/tools/CreditsTool/bin/*
+/tools/CreditsTool/obj/*
#GitHub Atom
.atom-build.json
@@ -228,13 +189,10 @@ tools/CreditsTool/obj/*
!/config/title_screens/images/exclude
#Linux docker
-tools/LinuxOneShot/SetupProgram/obj/*
-tools/LinuxOneShot/SetupProgram/bin/*
-tools/LinuxOneShot/SetupProgram/.vs
-tools/LinuxOneShot/Database
-tools/LinuxOneShot/TGS_Config
-tools/LinuxOneShot/TGS_Instances
-tools/LinuxOneShot/TGS_Logs
-
-# Common build tooling
-!/tools/build
+/tools/LinuxOneShot/SetupProgram/obj/*
+/tools/LinuxOneShot/SetupProgram/bin/*
+/tools/LinuxOneShot/SetupProgram/.vs
+/tools/LinuxOneShot/Database
+/tools/LinuxOneShot/TGS_Config
+/tools/LinuxOneShot/TGS_Instances
+/tools/LinuxOneShot/TGS_Logs
diff --git a/Build.bat b/Build.bat
index dd3a6fd9d9..68eaef0c2d 100644
--- a/Build.bat
+++ b/Build.bat
@@ -1,2 +1,3 @@
-@call tools\build\build
-@pause
+@echo off
+call "%~dp0\tools\build\build.bat" %*
+pause
diff --git a/CLEAN.bat b/CLEAN.bat
new file mode 100644
index 0000000000..47293bb769
--- /dev/null
+++ b/CLEAN.bat
@@ -0,0 +1,3 @@
+@echo off
+call "%~dp0\tools\build\build.bat" dist-clean
+pause
diff --git a/RUN_SERVER.bat b/RUN_SERVER.bat
new file mode 100644
index 0000000000..93438f0c2e
--- /dev/null
+++ b/RUN_SERVER.bat
@@ -0,0 +1,3 @@
+@echo off
+call "%~dp0\tools\build\build.bat" server %*
+pause
diff --git a/tools/build/README.md b/tools/build/README.md
index f367857158..51121dbde6 100644
--- a/tools/build/README.md
+++ b/tools/build/README.md
@@ -13,6 +13,14 @@ This build script is the recommended way to compile the game, including not only
The script will skip build steps whose inputs have not changed since the last run.
+## Getting list of available targets
+
+You can get a list of all targets that you can build by running the following command:
+
+```
+tools/build/build --help
+```
+
## Dependencies
- On Windows, `BUILD.bat` will automatically install a private (vendored) copy of Node.
@@ -22,3 +30,5 @@ The script will skip build steps whose inputs have not changed since the last ru
## Why?
We used to include compiled versions of the tgui JavaScript code in the Git repository so that the project could be compiled using BYOND only. These pre-compiled files tended to have merge conflicts for no good reason. Using a build script lets us avoid this problem, while keeping builds convenient for people who are not modifying tgui.
+
+This build script is based on [Juke Build](https://github.com/stylemistake/juke-build) - please follow the link and read the documentation for the project to understand how it works and how to contribute to this build script.
diff --git a/tools/build/binaries/README.md b/tools/build/binaries/README.md
deleted file mode 100644
index 625f337d98..0000000000
--- a/tools/build/binaries/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This directory is used to store temporary files to create binaries on linux
\ No newline at end of file
diff --git a/tools/build/build b/tools/build/build
index cd4d804e8f..0e202e1bba 100755
--- a/tools/build/build
+++ b/tools/build/build
@@ -1,6 +1,4 @@
#!/bin/sh
-
-#Build TGUI
set -e
cd "$(dirname "$0")"
exec ../bootstrap/node build.js "$@"
diff --git a/tools/build/build.bat b/tools/build/build.bat
index f5d9bd48f3..56e3bf1171 100644
--- a/tools/build/build.bat
+++ b/tools/build/build.bat
@@ -1 +1,2 @@
-@"%~dp0\..\bootstrap\node" "%~dp0\build.js"
+@echo off
+"%~dp0\..\bootstrap\node.bat" --experimental-modules "%~dp0\build.js" %*
diff --git a/tools/build/build.js b/tools/build/build.js
index 0f04441334..f8d3a9a7dd 100755
--- a/tools/build/build.js
+++ b/tools/build/build.js
@@ -1,225 +1,293 @@
#!/usr/bin/env node
/**
+ * Build script for /tg/station 13 codebase.
+ *
+ * This script uses Juke Build, read the docs here:
+ * https://github.com/stylemistake/juke-build
+ *
* @file
- * @copyright 2020 Aleksej Komarov
+ * @copyright 2021 Aleksej Komarov
* @license MIT
*/
-// Change working directory to project root
-process.chdir(require('path').resolve(__dirname, '../../'));
+import fs from 'fs';
+import { DreamDaemon, DreamMaker } from './lib/byond.js';
+import { yarn } from './lib/yarn.js';
+import Juke from './juke/index.js';
-// Validate NodeJS version
-const NODE_VERSION = parseInt(process.versions.node.match(/(\d+)/)[1]);
-const NODE_VERSION_TARGET = parseInt(require('fs')
- .readFileSync('dependencies.sh', 'utf-8')
- .match(/NODE_VERSION=(\d+)/)[1]);
-if (NODE_VERSION < NODE_VERSION_TARGET) {
- console.error('Your current Node.js version is out of date.');
- console.error('You have two options:');
- console.error(' a) Go to https://nodejs.org/ and install the latest LTS release of Node.js');
- console.error(' b) Uninstall Node.js (our build system automatically downloads one)');
- process.exit(1);
-}
+Juke.chdir('../..', import.meta.url);
+Juke.setup({ file: import.meta.url }).then((code) => process.exit(code));
-const STANDARD_BUILD = "Standard Build"
-const TGS_BUILD = "TGS Build"
-const ALL_MAPS_BUILD = "CI All Maps Build"
-const TEST_RUN_BUILD = "CI Integration Tests Build"
-const NO_DM_BUILD = "Except DM Build"
+const DME_NAME = 'tgstation';
-let BUILD_MODE = STANDARD_BUILD;
-if (process.env.CBT_BUILD_MODE) {
- switch (process.env.CBT_BUILD_MODE) {
- case "ALL_MAPS":
- BUILD_MODE = ALL_MAPS_BUILD
- break;
- case "TEST_RUN":
- BUILD_MODE = TEST_RUN_BUILD
- break;
- case "TGS":
- BUILD_MODE = TGS_BUILD
- break;
- case "NO_DM":
- BUILD_MODE = NO_DM_BUILD
- break;
- default:
- BUILD_MODE = process.env.CBT_BUILD_MODE
- break;
- }
-}
-console.log(`Starting CBT in ${BUILD_MODE} mode.`)
+export const DefineParameter = new Juke.Parameter({
+ type: 'string[]',
+ alias: 'D',
+});
-const DME_NAME = 'tgstation'
+export const PortParameter = new Juke.Parameter({
+ type: 'string',
+ alias: 'p',
+});
-// Main
-// --------------------------------------------------------
+export const CiParameter = new Juke.Parameter({
+ type: 'boolean',
+});
-const { resolveGlob, stat } = require('./cbt/fs');
-const { exec } = require('./cbt/process');
-const { Task, runTasks } = require('./cbt/task');
-const { regQuery } = require('./cbt/winreg');
-const fs = require('fs');
+export const DmMapsIncludeTarget = new Juke.Target({
+ executes: async () => {
+ const folders = [
+ ...Juke.glob('_maps/RandomRuins/**/*.dmm'),
+ ...Juke.glob('_maps/RandomZLevels/**/*.dmm'),
+ ...Juke.glob('_maps/shuttles/**/*.dmm'),
+ ...Juke.glob('_maps/templates/**/*.dmm'),
+ ];
+ const content = folders
+ .map((file) => file.replace('_maps/', ''))
+ .map((file) => `#include "${file}"`)
+ .join('\n') + '\n';
+ fs.writeFileSync('_maps/templates.dm', content);
+ },
+});
-const yarn = args => {
- const yarnPath = resolveGlob('./tgui/.yarn/releases/yarn-*.cjs')[0]
- .replace('/tgui/', '/');
- return exec('node', [yarnPath, ...args], {
- cwd: './tgui',
- });
-};
+export const DmTarget = new Juke.Target({
+ dependsOn: ({ get }) => [
+ get(DefineParameter).includes('ALL_MAPS') && DmMapsIncludeTarget,
+ ],
+ inputs: [
+ '_maps/map_files/generic/**',
+ 'code/**',
+ 'goon/**',
+ 'html/**',
+ 'icons/**',
+ 'interface/**',
+ `${DME_NAME}.dme`,
+ ],
+ outputs: [
+ `${DME_NAME}.dmb`,
+ `${DME_NAME}.rsc`,
+ ],
+ parameters: [DefineParameter],
+ executes: async ({ get }) => {
+ const defines = get(DefineParameter);
+ if (defines.length > 0) {
+ Juke.logger.info('Using defines:', defines.join(', '));
+ }
+ await DreamMaker(`${DME_NAME}.dme`, {
+ defines: ['CBT', ...defines],
+ });
+ },
+});
-/** Installs all tgui dependencies */
-const taskYarn = new Task('yarn')
- // The following dependencies skip what could be considered an important
- // step in Yarn: it verifies the integrity of cache. With this setup, if
- // cache ever becomes corrupted, your only option is to clean build.
- .depends('tgui/.yarn/+(cache|releases|plugins|sdks)/**/*')
- .depends('tgui/**/package.json')
- .depends('tgui/yarn.lock')
- // Phony target (automatically created at the end of the task)
- .provides('tgui/.yarn/install-target')
- .build(() => yarn(['install']));
+export const DmTestTarget = new Juke.Target({
+ dependsOn: ({ get }) => [
+ get(DefineParameter).includes('ALL_MAPS') && DmMapsIncludeTarget,
+ ],
+ executes: async ({ get }) => {
+ const defines = get(DefineParameter);
+ if (defines.length > 0) {
+ Juke.logger.info('Using defines:', defines.join(', '));
+ }
+ fs.copyFileSync(`${DME_NAME}.dme`, `${DME_NAME}.test.dme`);
+ await DreamMaker(`${DME_NAME}.test.dme`, {
+ defines: ['CBT', 'CIBUILDING', ...defines],
+ });
+ Juke.rm('data/logs/ci', { recursive: true });
+ await DreamDaemon(
+ `${DME_NAME}.test.dmb`,
+ '-close', '-trusted', '-verbose',
+ '-params', 'log-directory=ci'
+ );
+ Juke.rm('*.test.*');
+ try {
+ const cleanRun = fs.readFileSync('data/logs/ci/clean_run.lk', 'utf-8');
+ console.log(cleanRun);
+ }
+ catch (err) {
+ Juke.logger.error('Test run was not clean, exiting');
+ throw new Juke.ExitCode(1);
+ }
+ },
+});
-/** Builds svg fonts */
-const taskTgfont = new Task('tgfont')
- .depends('tgui/.yarn/install-target')
- .depends('tgui/packages/tgfont/**/*.+(js|cjs|svg)')
- .depends('tgui/packages/tgfont/package.json')
- .provides('tgui/packages/tgfont/dist/tgfont.css')
- .provides('tgui/packages/tgfont/dist/tgfont.eot')
- .provides('tgui/packages/tgfont/dist/tgfont.woff2')
- .build(() => yarn(['workspace', 'tgfont', 'build']));
+export const YarnTarget = new Juke.Target({
+ inputs: [
+ 'tgui/.yarn/+(cache|releases|plugins|sdks)/**/*',
+ 'tgui/**/package.json',
+ 'tgui/yarn.lock',
+ ],
+ outputs: [
+ 'tgui/.yarn/install-target',
+ ],
+ executes: async () => {
+ await yarn('install');
+ },
+});
-/** Builds tgui */
-const taskTgui = new Task('tgui')
- .depends('tgui/.yarn/install-target')
- .depends('tgui/webpack.config.js')
- .depends('tgui/**/package.json')
- .depends('tgui/packages/**/*.+(js|cjs|ts|tsx|scss)')
- .provides('tgui/public/tgui.bundle.css')
- .provides('tgui/public/tgui.bundle.js')
- .provides('tgui/public/tgui-common.bundle.js')
- .provides('tgui/public/tgui-panel.bundle.css')
- .provides('tgui/public/tgui-panel.bundle.js')
- .build(async () => {
- await yarn(['run', 'webpack-cli', '--mode=production']);
- });
+export const TgFontTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ inputs: [
+ 'tgui/.yarn/install-target',
+ 'tgui/packages/tgfont/**/*.+(js|cjs|svg)',
+ 'tgui/packages/tgfont/package.json',
+ ],
+ outputs: [
+ 'tgui/packages/tgfont/dist/tgfont.css',
+ 'tgui/packages/tgfont/dist/tgfont.eot',
+ 'tgui/packages/tgfont/dist/tgfont.woff2',
+ ],
+ executes: async () => {
+ await yarn('workspace', 'tgfont', 'build');
+ },
+});
+
+export const TguiTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ inputs: [
+ 'tgui/.yarn/install-target',
+ 'tgui/webpack.config.js',
+ 'tgui/**/package.json',
+ 'tgui/packages/**/*.+(js|cjs|ts|tsx|scss)',
+ ],
+ outputs: [
+ 'tgui/public/tgui.bundle.css',
+ 'tgui/public/tgui.bundle.js',
+ 'tgui/public/tgui-panel.bundle.css',
+ 'tgui/public/tgui-panel.bundle.js',
+ ],
+ executes: async () => {
+ await yarn('webpack-cli', '--mode=production');
+ },
+});
+
+export const TguiEslintTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ executes: async ({ args }) => {
+ await yarn(
+ 'eslint', 'packages',
+ '--fix', '--ext', '.js,.cjs,.ts,.tsx',
+ ...args
+ );
+ },
+});
+
+export const TguiTscTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ executes: async () => {
+ await yarn('tsc');
+ },
+});
+
+export const TguiTestTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ executes: async ({ args }) => {
+ await yarn('jest', ...args);
+ },
+});
+
+export const TguiLintTarget = new Juke.Target({
+ dependsOn: [YarnTarget, TguiEslintTarget, TguiTscTarget, TguiTestTarget],
+});
+
+export const TguiDevTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ executes: async ({ args }) => {
+ await yarn('node', 'packages/tgui-dev-server/index.js', ...args);
+ },
+});
+
+export const TguiAnalyzeTarget = new Juke.Target({
+ dependsOn: [YarnTarget],
+ executes: async () => {
+ await yarn('webpack-cli', '--mode=production', '--analyze');
+ },
+});
+
+export const TestTarget = new Juke.Target({
+ dependsOn: [DmTestTarget, TguiTestTarget],
+});
+
+export const LintTarget = new Juke.Target({
+ dependsOn: [TguiLintTarget],
+});
+
+export const BuildTarget = new Juke.Target({
+ dependsOn: [TguiTarget, TgFontTarget, DmTarget],
+});
+
+export const ServerTarget = new Juke.Target({
+ dependsOn: [BuildTarget],
+ executes: async ({ get }) => {
+ const port = get(PortParameter) || '1337';
+ await DreamDaemon(`${DME_NAME}.dmb`, port, '-trusted');
+ },
+});
+
+export const AllTarget = new Juke.Target({
+ dependsOn: [TestTarget, LintTarget, BuildTarget],
+});
+
+/**
+ * Removes the immediate build junk to produce clean builds.
+ */
+export const CleanTarget = new Juke.Target({
+ executes: async () => {
+ Juke.rm('*.dmb');
+ Juke.rm('*.rsc');
+ Juke.rm('*.mdme');
+ Juke.rm('*.mdme*');
+ Juke.rm('*.m.*');
+ Juke.rm('_maps/templates.dm');
+ Juke.rm('tgui/public/.tmp', { recursive: true });
+ Juke.rm('tgui/public/*.map');
+ Juke.rm('tgui/public/*.chunk.*');
+ Juke.rm('tgui/public/*.bundle.*');
+ Juke.rm('tgui/public/*.hot-update.*');
+ Juke.rm('tgui/packages/tgfont/dist', { recursive: true });
+ Juke.rm('tgui/.yarn/cache', { recursive: true });
+ Juke.rm('tgui/.yarn/unplugged', { recursive: true });
+ Juke.rm('tgui/.yarn/webpack', { recursive: true });
+ Juke.rm('tgui/.yarn/build-state.yml');
+ Juke.rm('tgui/.yarn/install-state.gz');
+ Juke.rm('tgui/.yarn/install-target');
+ Juke.rm('tgui/.pnp.*');
+ },
+});
+
+/**
+ * Removes more junk at expense of much slower initial builds.
+ */
+export const DistCleanTarget = new Juke.Target({
+ dependsOn: [CleanTarget],
+ executes: async () => {
+ Juke.logger.info('Cleaning up data/logs');
+ Juke.rm('data/logs', { recursive: true });
+ Juke.logger.info('Cleaning up bootstrap cache');
+ Juke.rm('tools/bootstrap/.cache', { recursive: true });
+ Juke.logger.info('Cleaning up global yarn cache');
+ await yarn('cache', 'clean', '--all');
+ },
+});
/**
* Prepends the defines to the .dme.
* Does not clean them up, as this is intended for TGS which
* clones new copies anyway.
*/
-const taskPrependDefines = (...defines) => new Task('prepend-defines')
- .build(async () => {
- const dmeContents = fs.readFileSync(`${DME_NAME}.dme`);
- const textToWrite = defines.map(define => `#define ${define}\n`);
- fs.writeFileSync(`${DME_NAME}.dme`, `${textToWrite}\n${dmeContents}`);
- });
+const prependDefines = (...defines) => {
+ const dmeContents = fs.readFileSync(`${DME_NAME}.dme`);
+ const textToWrite = defines.map(define => `#define ${define}\n`);
+ fs.writeFileSync(`${DME_NAME}.dme`, `${textToWrite}\n${dmeContents}`);
+};
-const taskDm = (...injectedDefines) => new Task('dm')
- .depends('_maps/map_files/generic/**')
- .depends('code/**')
- .depends('goon/**')
- .depends('html/**')
- .depends('icons/**')
- .depends('interface/**')
- .depends(process.platform === 'win32' ? 'auxmos.*' : 'libauxmos.*')
- .depends('tgui/public/tgui.html')
- .depends('tgui/public/*.bundle.*')
- .depends(`${DME_NAME}.dme`)
- .provides(`${DME_NAME}.dmb`)
- .provides(`${DME_NAME}.rsc`)
- .build(async () => {
- const dmPath = await (async () => {
- // Search in array of paths
- const paths = [
- ...((process.env.DM_EXE && process.env.DM_EXE.split(',')) || []),
- 'C:\\Program Files\\BYOND\\bin\\dm.exe',
- 'C:\\Program Files (x86)\\BYOND\\bin\\dm.exe',
- ['reg', 'HKLM\\Software\\Dantom\\BYOND', 'installpath'],
- ['reg', 'HKLM\\SOFTWARE\\WOW6432Node\\Dantom\\BYOND', 'installpath'],
- ];
- const isFile = path => {
- try {
- const fstat = stat(path);
- return fstat && fstat.isFile();
- }
- catch (err) {}
- return false;
- };
- for (let path of paths) {
- // Resolve a registry key
- if (Array.isArray(path)) {
- const [type, ...args] = path;
- path = await regQuery(...args);
- }
- if (!path) {
- continue;
- }
- // Check if path exists
- if (isFile(path)) {
- return path;
- }
- if (isFile(path + '/dm.exe')) {
- return path + '/dm.exe';
- }
- if (isFile(path + '/bin/dm.exe')) {
- return path + '/bin/dm.exe';
- }
- }
- // Default paths
- return (
- process.platform === 'win32' && 'dm.exe'
- || 'DreamMaker'
- );
- })();
- if (injectedDefines.length) {
- const injectedContent = injectedDefines
- .map(x => `#define ${x}\n`)
- .join('')
- // Create mdme file
- fs.writeFileSync(`${DME_NAME}.mdme`, injectedContent)
- // Add the actual dme content
- const dme_content = fs.readFileSync(`${DME_NAME}.dme`)
- fs.appendFileSync(`${DME_NAME}.mdme`, dme_content)
- await exec(dmPath, [`${DME_NAME}.mdme`]);
- // Rename dmb
- fs.renameSync(`${DME_NAME}.mdme.dmb`, `${DME_NAME}.dmb`)
- // Rename rsc
- fs.renameSync(`${DME_NAME}.mdme.rsc`, `${DME_NAME}.rsc`)
- // Remove mdme
- fs.unlinkSync(`${DME_NAME}.mdme`)
- }
- else {
- await exec(dmPath, [`${DME_NAME}.dme`]);
- }
- });
+export const TgsTarget = new Juke.Target({
+ dependsOn: [TguiTarget, TgFontTarget],
+ executes: async () => {
+ Juke.logger.info('Prepending TGS define');
+ prependDefines('TGS');
+ },
+});
-// Frontend
-let tasksToRun = [
- taskYarn,
- taskTgfont,
- taskTgui,
-];
-switch (BUILD_MODE) {
- case STANDARD_BUILD:
- tasksToRun.push(taskDm('CBT'));
- break;
- case TGS_BUILD:
- tasksToRun.push(taskPrependDefines('TGS'));
- break;
- case ALL_MAPS_BUILD:
- tasksToRun.push(taskDm('CBT','CIBUILDING','CITESTING','ALL_MAPS'));
- break;
- case TEST_RUN_BUILD:
- tasksToRun.push(taskDm('CBT','CIBUILDING'));
- break;
- case NO_DM_BUILD:
- break;
- default:
- console.error(`Unknown build mode : ${BUILD_MODE}`)
- break;
-}
+const TGS_MODE = process.env.CBT_BUILD_MODE === 'TGS';
-runTasks(tasksToRun);
+export default TGS_MODE ? TgsTarget : BuildTarget;
diff --git a/tools/build/build.sh b/tools/build/build.sh
deleted file mode 100755
index 62372eff2d..0000000000
--- a/tools/build/build.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/sh
-
-#Detect OS and use corresponding package manager for dependencies. Currently only works for arch, debian/ubuntu, and RHEL/fedora/CentOS
-if [[ -f '/etc/arch-release' ]]; then
- echo -ne '\n y' | sudo pacman --needed -Sy base-devel git curl nodejs unzip
-fi
-if [[ -f '/etc/debian version' ]]; then
- sudo dpkg --add-architecture i386
- sudo apt-get update
- sudo apt-get install -y build-essential git curl lib32z1 pkg-config libssl-dev:i386 libssl-dev nodejs unzip g++-multilib libc6-i386 libstdc++6:i386
-fi
-if [[ -f '/etc/centos-release' ]] || [[ -f '/etc/fedora-release' ]]; then #DNF should work for both of these
- sudo dnf --refresh install make automake gcc gcc-c++ kernel-devel git curl unzip glibc-devel.i686 openssl-devel.i686 libgcc.i686 libstdc++-devel.i686
-fi
-
-cd binaries
-
-#Install rust if not present
-if ! [ -x "$has_cargo" ]; then
- echo "Installing rust..."
- curl https://sh.rustup.rs -sSf | sh -s -- -y
- . ~/.profile
-fi
-
-#Download/update rust-g repo
-if [ ! -d "rust-g" ]; then
- echo "Cloning rust-g..."
- git clone https://github.com/tgstation/rust-g
- cd rust-g
- ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
-else
- echo "Fetching rust-g..."
- cd rust-g
- git fetch
- ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
-fi
-
-#Compile and move rust-g binary to repo root
-echo "Deploying rust-g..."
-git checkout "$RUST_G_VERSION"
-env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo build --release --target=i686-unknown-linux-gnu
-mv target/i686-unknown-linux-gnu/release/librust_g.so ../../../../librust_g.so
-cd ..
-
-#Download/update auxmos repo
-if [ ! -d "auxmos" ]; then
- echo "Cloning auxmos..."
- git clone https://github.com/Putnam3145/auxmos
- cd auxmos
- ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
-else
- echo "Fetching auxmos..."
- cd auxmos
- git fetch
- ~/.cargo/bin/rustup target add i686-unknown-linux-gnu
-fi
-
-#Compile and move auxmos binary to repo root
-echo "Deploying auxmos..."
-git checkout "$AUXMOS_VERSION"
-env PKG_CONFIG_ALLOW_CROSS=1 ~/.cargo/bin/cargo rustc --release --target=i686-unknown-linux-gnu --features all_reaction_hooks,explosive_decompression -- -C target-cpu=native
-mv target/i686-unknown-linux-gnu/release/libauxmos.so ../../../../libauxmos.so
-cd ../..
-
-#Install BYOND
-cd ../..
-./tools/ci/install_byond.sh
-source $HOME/BYOND/byond/bin/byondsetup
-
-cd tools/build
-
-#Build TGUI
-set -e
-cd "$(dirname "$0")"
-exec ../bootstrap/node build.js "$@"
diff --git a/tools/build/cbt/fs.js b/tools/build/cbt/fs.js
deleted file mode 100644
index 68a5a8bfbf..0000000000
--- a/tools/build/cbt/fs.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/**
- * @file
- * @copyright 2020 Aleksej Komarov
- * @license MIT
- */
-
-const fs = require('fs');
-const glob = require('./glob');
-
-class File {
- constructor(path) {
- this.path = path;
- }
-
- get stat() {
- if (this._stat === undefined) {
- this._stat = stat(this.path);
- }
- return this._stat;
- }
-
- exists() {
- return this.stat !== null;
- }
-
- get mtime() {
- return this.stat && this.stat.mtime;
- }
-
- touch() {
- const time = new Date();
- try {
- fs.utimesSync(this.path, time, time);
- }
- catch (err) {
- fs.closeSync(fs.openSync(this.path, 'w'));
- }
- }
-}
-
-class Glob {
- constructor(path) {
- this.path = path;
- }
-
- toFiles() {
- const paths = glob.sync(this.path, {
- strict: false,
- silent: true,
- });
- return paths
- .map(path => new File(path))
- .filter(file => file.exists());
- }
-}
-
-/**
- * If true, source is newer than target.
- * @param {File[]} sources
- * @param {File[]} targets
- */
-const compareFiles = (sources, targets) => {
- let bestSource = null;
- let bestTarget = null;
- for (const file of sources) {
- if (!bestSource || file.mtime > bestSource.mtime) {
- bestSource = file;
- }
- }
- for (const file of targets) {
- if (!file.exists()) {
- return `target '${file.path}' is missing`;
- }
- if (!bestTarget || file.mtime < bestTarget.mtime) {
- bestTarget = file;
- }
- }
- // Doesn't need rebuild if there is no source, but target exists.
- if (!bestSource) {
- if (bestTarget) {
- return false;
- }
- return 'no known sources or targets';
- }
- // Always needs a rebuild if no targets were specified (e.g. due to GLOB).
- if (!bestTarget) {
- return 'no targets were specified';
- }
- // Needs rebuild if source is newer than target
- if (bestSource.mtime > bestTarget.mtime) {
- return `source '${bestSource.path}' is newer than target '${bestTarget.path}'`;
- }
- return false;
-};
-
-/**
- * Returns file stats for the provided path, or null if file is
- * not accessible.
- */
-const stat = path => {
- try {
- return fs.statSync(path);
- }
- catch {
- return null;
- }
-};
-
-/**
- * Resolves a glob pattern and returns files that are safe
- * to call `stat` on.
- */
-const resolveGlob = globPath => {
- const unsafePaths = glob.sync(globPath, {
- strict: false,
- silent: true,
- });
- const safePaths = [];
- for (let path of unsafePaths) {
- try {
- fs.statSync(path);
- safePaths.push(path);
- }
- catch {}
- }
- return safePaths;
-};
-
-module.exports = {
- File,
- Glob,
- compareFiles,
- stat,
- resolveGlob,
-};
diff --git a/tools/build/cbt/glob.js b/tools/build/cbt/glob.js
deleted file mode 100644
index df6e153b38..0000000000
--- a/tools/build/cbt/glob.js
+++ /dev/null
@@ -1,3281 +0,0 @@
-'use strict';
-
-var fs = require('fs');
-var path$1 = require('path');
-var util = require('util');
-var events = require('events');
-var assert = require('assert');
-
-function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
-
-var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
-var path__default = /*#__PURE__*/_interopDefaultLegacy(path$1);
-var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
-var events__default = /*#__PURE__*/_interopDefaultLegacy(events);
-var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
-
-// Copyright Joyent, Inc. and other Node contributors.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a
-// copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// distribute, sublicense, and/or sell copies of the Software, and to permit
-// persons to whom the Software is furnished to do so, subject to the
-// following conditions:
-//
-// The above copyright notice and this permission notice shall be included
-// in all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
-// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
-// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-// USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-
-var isWindows = process.platform === 'win32';
-
-
-// JavaScript implementation of realpath, ported from node pre-v6
-
-var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
-
-function rethrow() {
- // Only enable in debug mode. A backtrace uses ~1000 bytes of heap space and
- // is fairly slow to generate.
- var callback;
- if (DEBUG) {
- var backtrace = new Error;
- callback = debugCallback;
- } else
- callback = missingCallback;
-
- return callback;
-
- function debugCallback(err) {
- if (err) {
- backtrace.message = err.message;
- err = backtrace;
- missingCallback(err);
- }
- }
-
- function missingCallback(err) {
- if (err) {
- if (process.throwDeprecation)
- throw err; // Forgot a callback but don't know where? Use NODE_DEBUG=fs
- else if (!process.noDeprecation) {
- var msg = 'fs: missing callback ' + (err.stack || err.message);
- if (process.traceDeprecation)
- console.trace(msg);
- else
- console.error(msg);
- }
- }
- }
-}
-
-function maybeCallback(cb) {
- return typeof cb === 'function' ? cb : rethrow();
-}
-
-var normalize = path__default['default'].normalize;
-
-// Regexp that finds the next partion of a (partial) path
-// result is [base_with_slash, base], e.g. ['somedir/', 'somedir']
-if (isWindows) {
- var nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
-} else {
- var nextPartRe = /(.*?)(?:[\/]+|$)/g;
-}
-
-// Regex to find the device root, including trailing slash. E.g. 'c:\\'.
-if (isWindows) {
- var splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
-} else {
- var splitRootRe = /^[\/]*/;
-}
-
-var realpathSync = function realpathSync(p, cache) {
- // make p is absolute
- p = path__default['default'].resolve(p);
-
- if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
- return cache[p];
- }
-
- var original = p,
- seenLinks = {},
- knownHard = {};
-
- // current character position in p
- var pos;
- // the partial path so far, including a trailing slash if any
- var current;
- // the partial path without a trailing slash (except when pointing at a root)
- var base;
- // the partial path scanned in the previous round, with slash
- var previous;
-
- start();
-
- function start() {
- // Skip over roots
- var m = splitRootRe.exec(p);
- pos = m[0].length;
- current = m[0];
- base = m[0];
- previous = '';
-
- // On windows, check that the root exists. On unix there is no need.
- if (isWindows && !knownHard[base]) {
- fs__default['default'].lstatSync(base);
- knownHard[base] = true;
- }
- }
-
- // walk down the path, swapping out linked pathparts for their real
- // values
- // NB: p.length changes.
- while (pos < p.length) {
- // find the next part
- nextPartRe.lastIndex = pos;
- var result = nextPartRe.exec(p);
- previous = current;
- current += result[0];
- base = previous + result[1];
- pos = nextPartRe.lastIndex;
-
- // continue if not a symlink
- if (knownHard[base] || (cache && cache[base] === base)) {
- continue;
- }
-
- var resolvedLink;
- if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
- // some known symbolic link. no need to stat again.
- resolvedLink = cache[base];
- } else {
- var stat = fs__default['default'].lstatSync(base);
- if (!stat.isSymbolicLink()) {
- knownHard[base] = true;
- if (cache) cache[base] = base;
- continue;
- }
-
- // read the link if it wasn't read before
- // dev/ino always return 0 on windows, so skip the check.
- var linkTarget = null;
- if (!isWindows) {
- var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
- if (seenLinks.hasOwnProperty(id)) {
- linkTarget = seenLinks[id];
- }
- }
- if (linkTarget === null) {
- fs__default['default'].statSync(base);
- linkTarget = fs__default['default'].readlinkSync(base);
- }
- resolvedLink = path__default['default'].resolve(previous, linkTarget);
- // track this, if given a cache.
- if (cache) cache[base] = resolvedLink;
- if (!isWindows) seenLinks[id] = linkTarget;
- }
-
- // resolve the link, then start over
- p = path__default['default'].resolve(resolvedLink, p.slice(pos));
- start();
- }
-
- if (cache) cache[original] = p;
-
- return p;
-};
-
-
-var realpath = function realpath(p, cache, cb) {
- if (typeof cb !== 'function') {
- cb = maybeCallback(cache);
- cache = null;
- }
-
- // make p is absolute
- p = path__default['default'].resolve(p);
-
- if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
- return process.nextTick(cb.bind(null, null, cache[p]));
- }
-
- var original = p,
- seenLinks = {},
- knownHard = {};
-
- // current character position in p
- var pos;
- // the partial path so far, including a trailing slash if any
- var current;
- // the partial path without a trailing slash (except when pointing at a root)
- var base;
- // the partial path scanned in the previous round, with slash
- var previous;
-
- start();
-
- function start() {
- // Skip over roots
- var m = splitRootRe.exec(p);
- pos = m[0].length;
- current = m[0];
- base = m[0];
- previous = '';
-
- // On windows, check that the root exists. On unix there is no need.
- if (isWindows && !knownHard[base]) {
- fs__default['default'].lstat(base, function(err) {
- if (err) return cb(err);
- knownHard[base] = true;
- LOOP();
- });
- } else {
- process.nextTick(LOOP);
- }
- }
-
- // walk down the path, swapping out linked pathparts for their real
- // values
- function LOOP() {
- // stop if scanned past end of path
- if (pos >= p.length) {
- if (cache) cache[original] = p;
- return cb(null, p);
- }
-
- // find the next part
- nextPartRe.lastIndex = pos;
- var result = nextPartRe.exec(p);
- previous = current;
- current += result[0];
- base = previous + result[1];
- pos = nextPartRe.lastIndex;
-
- // continue if not a symlink
- if (knownHard[base] || (cache && cache[base] === base)) {
- return process.nextTick(LOOP);
- }
-
- if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
- // known symbolic link. no need to stat again.
- return gotResolvedLink(cache[base]);
- }
-
- return fs__default['default'].lstat(base, gotStat);
- }
-
- function gotStat(err, stat) {
- if (err) return cb(err);
-
- // if not a symlink, skip to the next path part
- if (!stat.isSymbolicLink()) {
- knownHard[base] = true;
- if (cache) cache[base] = base;
- return process.nextTick(LOOP);
- }
-
- // stat & read the link if not read before
- // call gotTarget as soon as the link target is known
- // dev/ino always return 0 on windows, so skip the check.
- if (!isWindows) {
- var id = stat.dev.toString(32) + ':' + stat.ino.toString(32);
- if (seenLinks.hasOwnProperty(id)) {
- return gotTarget(null, seenLinks[id], base);
- }
- }
- fs__default['default'].stat(base, function(err) {
- if (err) return cb(err);
-
- fs__default['default'].readlink(base, function(err, target) {
- if (!isWindows) seenLinks[id] = target;
- gotTarget(err, target);
- });
- });
- }
-
- function gotTarget(err, target, base) {
- if (err) return cb(err);
-
- var resolvedLink = path__default['default'].resolve(previous, target);
- if (cache) cache[base] = resolvedLink;
- gotResolvedLink(resolvedLink);
- }
-
- function gotResolvedLink(resolvedLink) {
- // resolve the link, then start over
- p = path__default['default'].resolve(resolvedLink, p.slice(pos));
- start();
- }
-};
-
-var old = {
- realpathSync: realpathSync,
- realpath: realpath
-};
-
-var fs_realpath = realpath$1;
-realpath$1.realpath = realpath$1;
-realpath$1.sync = realpathSync$1;
-realpath$1.realpathSync = realpathSync$1;
-realpath$1.monkeypatch = monkeypatch;
-realpath$1.unmonkeypatch = unmonkeypatch;
-
-
-var origRealpath = fs__default['default'].realpath;
-var origRealpathSync = fs__default['default'].realpathSync;
-
-var version = process.version;
-var ok = /^v[0-5]\./.test(version);
-
-
-function newError (er) {
- return er && er.syscall === 'realpath' && (
- er.code === 'ELOOP' ||
- er.code === 'ENOMEM' ||
- er.code === 'ENAMETOOLONG'
- )
-}
-
-function realpath$1 (p, cache, cb) {
- if (ok) {
- return origRealpath(p, cache, cb)
- }
-
- if (typeof cache === 'function') {
- cb = cache;
- cache = null;
- }
- origRealpath(p, cache, function (er, result) {
- if (newError(er)) {
- old.realpath(p, cache, cb);
- } else {
- cb(er, result);
- }
- });
-}
-
-function realpathSync$1 (p, cache) {
- if (ok) {
- return origRealpathSync(p, cache)
- }
-
- try {
- return origRealpathSync(p, cache)
- } catch (er) {
- if (newError(er)) {
- return old.realpathSync(p, cache)
- } else {
- throw er
- }
- }
-}
-
-function monkeypatch () {
- fs__default['default'].realpath = realpath$1;
- fs__default['default'].realpathSync = realpathSync$1;
-}
-
-function unmonkeypatch () {
- fs__default['default'].realpath = origRealpath;
- fs__default['default'].realpathSync = origRealpathSync;
-}
-
-var concatMap = function (xs, fn) {
- var res = [];
- for (var i = 0; i < xs.length; i++) {
- var x = fn(xs[i], i);
- if (isArray(x)) res.push.apply(res, x);
- else res.push(x);
- }
- return res;
-};
-
-var isArray = Array.isArray || function (xs) {
- return Object.prototype.toString.call(xs) === '[object Array]';
-};
-
-var balancedMatch = balanced;
-function balanced(a, b, str) {
- if (a instanceof RegExp) a = maybeMatch(a, str);
- if (b instanceof RegExp) b = maybeMatch(b, str);
-
- var r = range(a, b, str);
-
- return r && {
- start: r[0],
- end: r[1],
- pre: str.slice(0, r[0]),
- body: str.slice(r[0] + a.length, r[1]),
- post: str.slice(r[1] + b.length)
- };
-}
-
-function maybeMatch(reg, str) {
- var m = str.match(reg);
- return m ? m[0] : null;
-}
-
-balanced.range = range;
-function range(a, b, str) {
- var begs, beg, left, right, result;
- var ai = str.indexOf(a);
- var bi = str.indexOf(b, ai + 1);
- var i = ai;
-
- if (ai >= 0 && bi > 0) {
- begs = [];
- left = str.length;
-
- while (i >= 0 && !result) {
- if (i == ai) {
- begs.push(i);
- ai = str.indexOf(a, i + 1);
- } else if (begs.length == 1) {
- result = [ begs.pop(), bi ];
- } else {
- beg = begs.pop();
- if (beg < left) {
- left = beg;
- right = bi;
- }
-
- bi = str.indexOf(b, i + 1);
- }
-
- i = ai < bi && ai >= 0 ? ai : bi;
- }
-
- if (begs.length) {
- result = [ left, right ];
- }
- }
-
- return result;
-}
-
-var braceExpansion = expandTop;
-
-var escSlash = '\0SLASH'+Math.random()+'\0';
-var escOpen = '\0OPEN'+Math.random()+'\0';
-var escClose = '\0CLOSE'+Math.random()+'\0';
-var escComma = '\0COMMA'+Math.random()+'\0';
-var escPeriod = '\0PERIOD'+Math.random()+'\0';
-
-function numeric(str) {
- return parseInt(str, 10) == str
- ? parseInt(str, 10)
- : str.charCodeAt(0);
-}
-
-function escapeBraces(str) {
- return str.split('\\\\').join(escSlash)
- .split('\\{').join(escOpen)
- .split('\\}').join(escClose)
- .split('\\,').join(escComma)
- .split('\\.').join(escPeriod);
-}
-
-function unescapeBraces(str) {
- return str.split(escSlash).join('\\')
- .split(escOpen).join('{')
- .split(escClose).join('}')
- .split(escComma).join(',')
- .split(escPeriod).join('.');
-}
-
-
-// Basically just str.split(","), but handling cases
-// where we have nested braced sections, which should be
-// treated as individual members, like {a,{b,c},d}
-function parseCommaParts(str) {
- if (!str)
- return [''];
-
- var parts = [];
- var m = balancedMatch('{', '}', str);
-
- if (!m)
- return str.split(',');
-
- var pre = m.pre;
- var body = m.body;
- var post = m.post;
- var p = pre.split(',');
-
- p[p.length-1] += '{' + body + '}';
- var postParts = parseCommaParts(post);
- if (post.length) {
- p[p.length-1] += postParts.shift();
- p.push.apply(p, postParts);
- }
-
- parts.push.apply(parts, p);
-
- return parts;
-}
-
-function expandTop(str) {
- if (!str)
- return [];
-
- // I don't know why Bash 4.3 does this, but it does.
- // Anything starting with {} will have the first two bytes preserved
- // but *only* at the top level, so {},a}b will not expand to anything,
- // but a{},b}c will be expanded to [a}c,abc].
- // One could argue that this is a bug in Bash, but since the goal of
- // this module is to match Bash's rules, we escape a leading {}
- if (str.substr(0, 2) === '{}') {
- str = '\\{\\}' + str.substr(2);
- }
-
- return expand(escapeBraces(str), true).map(unescapeBraces);
-}
-
-function embrace(str) {
- return '{' + str + '}';
-}
-function isPadded(el) {
- return /^-?0\d/.test(el);
-}
-
-function lte(i, y) {
- return i <= y;
-}
-function gte(i, y) {
- return i >= y;
-}
-
-function expand(str, isTop) {
- var expansions = [];
-
- var m = balancedMatch('{', '}', str);
- if (!m || /\$$/.test(m.pre)) return [str];
-
- var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
- var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
- var isSequence = isNumericSequence || isAlphaSequence;
- var isOptions = m.body.indexOf(',') >= 0;
- if (!isSequence && !isOptions) {
- // {a},b}
- if (m.post.match(/,.*\}/)) {
- str = m.pre + '{' + m.body + escClose + m.post;
- return expand(str);
- }
- return [str];
- }
-
- var n;
- if (isSequence) {
- n = m.body.split(/\.\./);
- } else {
- n = parseCommaParts(m.body);
- if (n.length === 1) {
- // x{{a,b}}y ==> x{a}y x{b}y
- n = expand(n[0], false).map(embrace);
- if (n.length === 1) {
- var post = m.post.length
- ? expand(m.post, false)
- : [''];
- return post.map(function(p) {
- return m.pre + n[0] + p;
- });
- }
- }
- }
-
- // at this point, n is the parts, and we know it's not a comma set
- // with a single entry.
-
- // no need to expand pre, since it is guaranteed to be free of brace-sets
- var pre = m.pre;
- var post = m.post.length
- ? expand(m.post, false)
- : [''];
-
- var N;
-
- if (isSequence) {
- var x = numeric(n[0]);
- var y = numeric(n[1]);
- var width = Math.max(n[0].length, n[1].length);
- var incr = n.length == 3
- ? Math.abs(numeric(n[2]))
- : 1;
- var test = lte;
- var reverse = y < x;
- if (reverse) {
- incr *= -1;
- test = gte;
- }
- var pad = n.some(isPadded);
-
- N = [];
-
- for (var i = x; test(i, y); i += incr) {
- var c;
- if (isAlphaSequence) {
- c = String.fromCharCode(i);
- if (c === '\\')
- c = '';
- } else {
- c = String(i);
- if (pad) {
- var need = width - c.length;
- if (need > 0) {
- var z = new Array(need + 1).join('0');
- if (i < 0)
- c = '-' + z + c.slice(1);
- else
- c = z + c;
- }
- }
- }
- N.push(c);
- }
- } else {
- N = concatMap(n, function(el) { return expand(el, false) });
- }
-
- for (var j = 0; j < N.length; j++) {
- for (var k = 0; k < post.length; k++) {
- var expansion = pre + N[j] + post[k];
- if (!isTop || isSequence || expansion)
- expansions.push(expansion);
- }
- }
-
- return expansions;
-}
-
-var minimatch_1 = minimatch;
-minimatch.Minimatch = Minimatch;
-
-var path = { sep: '/' };
-try {
- path = path__default['default'];
-} catch (er) {}
-
-var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
-
-
-var plTypes = {
- '!': { open: '(?:(?!(?:', close: '))[^/]*?)'},
- '?': { open: '(?:', close: ')?' },
- '+': { open: '(?:', close: ')+' },
- '*': { open: '(?:', close: ')*' },
- '@': { open: '(?:', close: ')' }
-};
-
-// any single thing other than /
-// don't need to escape / when using new RegExp()
-var qmark = '[^/]';
-
-// * => any number of characters
-var star = qmark + '*?';
-
-// ** when dots are allowed. Anything goes, except .. and .
-// not (^ or / followed by one or two dots followed by $ or /),
-// followed by anything, any number of times.
-var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?';
-
-// not a ^ or / followed by a dot,
-// followed by anything, any number of times.
-var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?';
-
-// characters that need to be escaped in RegExp.
-var reSpecials = charSet('().*{}+?[]^$\\!');
-
-// "abc" -> { a:true, b:true, c:true }
-function charSet (s) {
- return s.split('').reduce(function (set, c) {
- set[c] = true;
- return set
- }, {})
-}
-
-// normalizes slashes.
-var slashSplit = /\/+/;
-
-minimatch.filter = filter;
-function filter (pattern, options) {
- options = options || {};
- return function (p, i, list) {
- return minimatch(p, pattern, options)
- }
-}
-
-function ext (a, b) {
- a = a || {};
- b = b || {};
- var t = {};
- Object.keys(b).forEach(function (k) {
- t[k] = b[k];
- });
- Object.keys(a).forEach(function (k) {
- t[k] = a[k];
- });
- return t
-}
-
-minimatch.defaults = function (def) {
- if (!def || !Object.keys(def).length) return minimatch
-
- var orig = minimatch;
-
- var m = function minimatch (p, pattern, options) {
- return orig.minimatch(p, pattern, ext(def, options))
- };
-
- m.Minimatch = function Minimatch (pattern, options) {
- return new orig.Minimatch(pattern, ext(def, options))
- };
-
- return m
-};
-
-Minimatch.defaults = function (def) {
- if (!def || !Object.keys(def).length) return Minimatch
- return minimatch.defaults(def).Minimatch
-};
-
-function minimatch (p, pattern, options) {
- if (typeof pattern !== 'string') {
- throw new TypeError('glob pattern string required')
- }
-
- if (!options) options = {};
-
- // shortcut: comments match nothing.
- if (!options.nocomment && pattern.charAt(0) === '#') {
- return false
- }
-
- // "" only matches ""
- if (pattern.trim() === '') return p === ''
-
- return new Minimatch(pattern, options).match(p)
-}
-
-function Minimatch (pattern, options) {
- if (!(this instanceof Minimatch)) {
- return new Minimatch(pattern, options)
- }
-
- if (typeof pattern !== 'string') {
- throw new TypeError('glob pattern string required')
- }
-
- if (!options) options = {};
- pattern = pattern.trim();
-
- // windows support: need to use /, not \
- if (path.sep !== '/') {
- pattern = pattern.split(path.sep).join('/');
- }
-
- this.options = options;
- this.set = [];
- this.pattern = pattern;
- this.regexp = null;
- this.negate = false;
- this.comment = false;
- this.empty = false;
-
- // make the set of regexps etc.
- this.make();
-}
-
-Minimatch.prototype.debug = function () {};
-
-Minimatch.prototype.make = make;
-function make () {
- // don't do it more than once.
- if (this._made) return
-
- var pattern = this.pattern;
- var options = this.options;
-
- // empty patterns and comments match nothing.
- if (!options.nocomment && pattern.charAt(0) === '#') {
- this.comment = true;
- return
- }
- if (!pattern) {
- this.empty = true;
- return
- }
-
- // step 1: figure out negation, etc.
- this.parseNegate();
-
- // step 2: expand braces
- var set = this.globSet = this.braceExpand();
-
- if (options.debug) this.debug = console.error;
-
- this.debug(this.pattern, set);
-
- // step 3: now we have a set, so turn each one into a series of path-portion
- // matching patterns.
- // These will be regexps, except in the case of "**", which is
- // set to the GLOBSTAR object for globstar behavior,
- // and will not contain any / characters
- set = this.globParts = set.map(function (s) {
- return s.split(slashSplit)
- });
-
- this.debug(this.pattern, set);
-
- // glob --> regexps
- set = set.map(function (s, si, set) {
- return s.map(this.parse, this)
- }, this);
-
- this.debug(this.pattern, set);
-
- // filter out everything that didn't compile properly.
- set = set.filter(function (s) {
- return s.indexOf(false) === -1
- });
-
- this.debug(this.pattern, set);
-
- this.set = set;
-}
-
-Minimatch.prototype.parseNegate = parseNegate;
-function parseNegate () {
- var pattern = this.pattern;
- var negate = false;
- var options = this.options;
- var negateOffset = 0;
-
- if (options.nonegate) return
-
- for (var i = 0, l = pattern.length
- ; i < l && pattern.charAt(i) === '!'
- ; i++) {
- negate = !negate;
- negateOffset++;
- }
-
- if (negateOffset) this.pattern = pattern.substr(negateOffset);
- this.negate = negate;
-}
-
-// Brace expansion:
-// a{b,c}d -> abd acd
-// a{b,}c -> abc ac
-// a{0..3}d -> a0d a1d a2d a3d
-// a{b,c{d,e}f}g -> abg acdfg acefg
-// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
-//
-// Invalid sets are not expanded.
-// a{2..}b -> a{2..}b
-// a{b}c -> a{b}c
-minimatch.braceExpand = function (pattern, options) {
- return braceExpand(pattern, options)
-};
-
-Minimatch.prototype.braceExpand = braceExpand;
-
-function braceExpand (pattern, options) {
- if (!options) {
- if (this instanceof Minimatch) {
- options = this.options;
- } else {
- options = {};
- }
- }
-
- pattern = typeof pattern === 'undefined'
- ? this.pattern : pattern;
-
- if (typeof pattern === 'undefined') {
- throw new TypeError('undefined pattern')
- }
-
- if (options.nobrace ||
- !pattern.match(/\{.*\}/)) {
- // shortcut. no need to expand.
- return [pattern]
- }
-
- return braceExpansion(pattern)
-}
-
-// parse a component of the expanded set.
-// At this point, no pattern may contain "/" in it
-// so we're going to return a 2d array, where each entry is the full
-// pattern, split on '/', and then turned into a regular expression.
-// A regexp is made at the end which joins each array with an
-// escaped /, and another full one which joins each regexp with |.
-//
-// Following the lead of Bash 4.1, note that "**" only has special meaning
-// when it is the *only* thing in a path portion. Otherwise, any series
-// of * is equivalent to a single *. Globstar behavior is enabled by
-// default, and can be disabled by setting options.noglobstar.
-Minimatch.prototype.parse = parse;
-var SUBPARSE = {};
-function parse (pattern, isSub) {
- if (pattern.length > 1024 * 64) {
- throw new TypeError('pattern is too long')
- }
-
- var options = this.options;
-
- // shortcuts
- if (!options.noglobstar && pattern === '**') return GLOBSTAR
- if (pattern === '') return ''
-
- var re = '';
- var hasMagic = !!options.nocase;
- var escaping = false;
- // ? => one single character
- var patternListStack = [];
- var negativeLists = [];
- var stateChar;
- var inClass = false;
- var reClassStart = -1;
- var classStart = -1;
- // . and .. never match anything that doesn't start with .,
- // even when options.dot is set.
- var patternStart = pattern.charAt(0) === '.' ? '' // anything
- // not (start or / followed by . or .. followed by / or end)
- : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
- : '(?!\\.)';
- var self = this;
-
- function clearStateChar () {
- if (stateChar) {
- // we had some state-tracking character
- // that wasn't consumed by this pass.
- switch (stateChar) {
- case '*':
- re += star;
- hasMagic = true;
- break
- case '?':
- re += qmark;
- hasMagic = true;
- break
- default:
- re += '\\' + stateChar;
- break
- }
- self.debug('clearStateChar %j %j', stateChar, re);
- stateChar = false;
- }
- }
-
- for (var i = 0, len = pattern.length, c
- ; (i < len) && (c = pattern.charAt(i))
- ; i++) {
- this.debug('%s\t%s %s %j', pattern, i, re, c);
-
- // skip over any that are escaped.
- if (escaping && reSpecials[c]) {
- re += '\\' + c;
- escaping = false;
- continue
- }
-
- switch (c) {
- case '/':
- // completely not allowed, even escaped.
- // Should already be path-split by now.
- return false
-
- case '\\':
- clearStateChar();
- escaping = true;
- continue
-
- // the various stateChar values
- // for the "extglob" stuff.
- case '?':
- case '*':
- case '+':
- case '@':
- case '!':
- this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c);
-
- // all of those are literals inside a class, except that
- // the glob [!a] means [^a] in regexp
- if (inClass) {
- this.debug(' in class');
- if (c === '!' && i === classStart + 1) c = '^';
- re += c;
- continue
- }
-
- // if we already have a stateChar, then it means
- // that there was something like ** or +? in there.
- // Handle the stateChar, then proceed with this one.
- self.debug('call clearStateChar %j', stateChar);
- clearStateChar();
- stateChar = c;
- // if extglob is disabled, then +(asdf|foo) isn't a thing.
- // just clear the statechar *now*, rather than even diving into
- // the patternList stuff.
- if (options.noext) clearStateChar();
- continue
-
- case '(':
- if (inClass) {
- re += '(';
- continue
- }
-
- if (!stateChar) {
- re += '\\(';
- continue
- }
-
- patternListStack.push({
- type: stateChar,
- start: i - 1,
- reStart: re.length,
- open: plTypes[stateChar].open,
- close: plTypes[stateChar].close
- });
- // negation is (?:(?!js)[^/]*)
- re += stateChar === '!' ? '(?:(?!(?:' : '(?:';
- this.debug('plType %j %j', stateChar, re);
- stateChar = false;
- continue
-
- case ')':
- if (inClass || !patternListStack.length) {
- re += '\\)';
- continue
- }
-
- clearStateChar();
- hasMagic = true;
- var pl = patternListStack.pop();
- // negation is (?:(?!js)[^/]*)
- // The others are (?:)
- re += pl.close;
- if (pl.type === '!') {
- negativeLists.push(pl);
- }
- pl.reEnd = re.length;
- continue
-
- case '|':
- if (inClass || !patternListStack.length || escaping) {
- re += '\\|';
- escaping = false;
- continue
- }
-
- clearStateChar();
- re += '|';
- continue
-
- // these are mostly the same in regexp and glob
- case '[':
- // swallow any state-tracking char before the [
- clearStateChar();
-
- if (inClass) {
- re += '\\' + c;
- continue
- }
-
- inClass = true;
- classStart = i;
- reClassStart = re.length;
- re += c;
- continue
-
- case ']':
- // a right bracket shall lose its special
- // meaning and represent itself in
- // a bracket expression if it occurs
- // first in the list. -- POSIX.2 2.8.3.2
- if (i === classStart + 1 || !inClass) {
- re += '\\' + c;
- escaping = false;
- continue
- }
-
- // handle the case where we left a class open.
- // "[z-a]" is valid, equivalent to "\[z-a\]"
- if (inClass) {
- // split where the last [ was, make sure we don't have
- // an invalid re. if so, re-walk the contents of the
- // would-be class to re-translate any characters that
- // were passed through as-is
- // TODO: It would probably be faster to determine this
- // without a try/catch and a new RegExp, but it's tricky
- // to do safely. For now, this is safe and works.
- var cs = pattern.substring(classStart + 1, i);
- try {
- RegExp('[' + cs + ']');
- } catch (er) {
- // not a valid class!
- var sp = this.parse(cs, SUBPARSE);
- re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]';
- hasMagic = hasMagic || sp[1];
- inClass = false;
- continue
- }
- }
-
- // finish up the class.
- hasMagic = true;
- inClass = false;
- re += c;
- continue
-
- default:
- // swallow any state char that wasn't consumed
- clearStateChar();
-
- if (escaping) {
- // no need
- escaping = false;
- } else if (reSpecials[c]
- && !(c === '^' && inClass)) {
- re += '\\';
- }
-
- re += c;
-
- } // switch
- } // for
-
- // handle the case where we left a class open.
- // "[abc" is valid, equivalent to "\[abc"
- if (inClass) {
- // split where the last [ was, and escape it
- // this is a huge pita. We now have to re-walk
- // the contents of the would-be class to re-translate
- // any characters that were passed through as-is
- cs = pattern.substr(classStart + 1);
- sp = this.parse(cs, SUBPARSE);
- re = re.substr(0, reClassStart) + '\\[' + sp[0];
- hasMagic = hasMagic || sp[1];
- }
-
- // handle the case where we had a +( thing at the *end*
- // of the pattern.
- // each pattern list stack adds 3 chars, and we need to go through
- // and escape any | chars that were passed through as-is for the regexp.
- // Go through and escape them, taking care not to double-escape any
- // | chars that were already escaped.
- for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
- var tail = re.slice(pl.reStart + pl.open.length);
- this.debug('setting tail', re, pl);
- // maybe some even number of \, then maybe 1 \, followed by a |
- tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) {
- if (!$2) {
- // the | isn't already escaped, so escape it.
- $2 = '\\';
- }
-
- // need to escape all those slashes *again*, without escaping the
- // one that we need for escaping the | character. As it works out,
- // escaping an even number of slashes can be done by simply repeating
- // it exactly after itself. That's why this trick works.
- //
- // I am sorry that you have to see this.
- return $1 + $1 + $2 + '|'
- });
-
- this.debug('tail=%j\n %s', tail, tail, pl, re);
- var t = pl.type === '*' ? star
- : pl.type === '?' ? qmark
- : '\\' + pl.type;
-
- hasMagic = true;
- re = re.slice(0, pl.reStart) + t + '\\(' + tail;
- }
-
- // handle trailing things that only matter at the very end.
- clearStateChar();
- if (escaping) {
- // trailing \\
- re += '\\\\';
- }
-
- // only need to apply the nodot start if the re starts with
- // something that could conceivably capture a dot
- var addPatternStart = false;
- switch (re.charAt(0)) {
- case '.':
- case '[':
- case '(': addPatternStart = true;
- }
-
- // Hack to work around lack of negative lookbehind in JS
- // A pattern like: *.!(x).!(y|z) needs to ensure that a name
- // like 'a.xyz.yz' doesn't match. So, the first negative
- // lookahead, has to look ALL the way ahead, to the end of
- // the pattern.
- for (var n = negativeLists.length - 1; n > -1; n--) {
- var nl = negativeLists[n];
-
- var nlBefore = re.slice(0, nl.reStart);
- var nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
- var nlLast = re.slice(nl.reEnd - 8, nl.reEnd);
- var nlAfter = re.slice(nl.reEnd);
-
- nlLast += nlAfter;
-
- // Handle nested stuff like *(*.js|!(*.json)), where open parens
- // mean that we should *not* include the ) in the bit that is considered
- // "after" the negated section.
- var openParensBefore = nlBefore.split('(').length - 1;
- var cleanAfter = nlAfter;
- for (i = 0; i < openParensBefore; i++) {
- cleanAfter = cleanAfter.replace(/\)[+*?]?/, '');
- }
- nlAfter = cleanAfter;
-
- var dollar = '';
- if (nlAfter === '' && isSub !== SUBPARSE) {
- dollar = '$';
- }
- var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast;
- re = newRe;
- }
-
- // if the re is not "" at this point, then we need to make sure
- // it doesn't match against an empty path part.
- // Otherwise a/* will match a/, which it should not.
- if (re !== '' && hasMagic) {
- re = '(?=.)' + re;
- }
-
- if (addPatternStart) {
- re = patternStart + re;
- }
-
- // parsing just a piece of a larger pattern.
- if (isSub === SUBPARSE) {
- return [re, hasMagic]
- }
-
- // skip the regexp for non-magical patterns
- // unescape anything in it, though, so that it'll be
- // an exact match against a file etc.
- if (!hasMagic) {
- return globUnescape(pattern)
- }
-
- var flags = options.nocase ? 'i' : '';
- try {
- var regExp = new RegExp('^' + re + '$', flags);
- } catch (er) {
- // If it was an invalid regular expression, then it can't match
- // anything. This trick looks for a character after the end of
- // the string, which is of course impossible, except in multi-line
- // mode, but it's not a /m regex.
- return new RegExp('$.')
- }
-
- regExp._glob = pattern;
- regExp._src = re;
-
- return regExp
-}
-
-minimatch.makeRe = function (pattern, options) {
- return new Minimatch(pattern, options || {}).makeRe()
-};
-
-Minimatch.prototype.makeRe = makeRe;
-function makeRe () {
- if (this.regexp || this.regexp === false) return this.regexp
-
- // at this point, this.set is a 2d array of partial
- // pattern strings, or "**".
- //
- // It's better to use .match(). This function shouldn't
- // be used, really, but it's pretty convenient sometimes,
- // when you just want to work with a regex.
- var set = this.set;
-
- if (!set.length) {
- this.regexp = false;
- return this.regexp
- }
- var options = this.options;
-
- var twoStar = options.noglobstar ? star
- : options.dot ? twoStarDot
- : twoStarNoDot;
- var flags = options.nocase ? 'i' : '';
-
- var re = set.map(function (pattern) {
- return pattern.map(function (p) {
- return (p === GLOBSTAR) ? twoStar
- : (typeof p === 'string') ? regExpEscape(p)
- : p._src
- }).join('\\\/')
- }).join('|');
-
- // must match entire pattern
- // ending in a * or ** will make it less strict.
- re = '^(?:' + re + ')$';
-
- // can match anything, as long as it's not this.
- if (this.negate) re = '^(?!' + re + ').*$';
-
- try {
- this.regexp = new RegExp(re, flags);
- } catch (ex) {
- this.regexp = false;
- }
- return this.regexp
-}
-
-minimatch.match = function (list, pattern, options) {
- options = options || {};
- var mm = new Minimatch(pattern, options);
- list = list.filter(function (f) {
- return mm.match(f)
- });
- if (mm.options.nonull && !list.length) {
- list.push(pattern);
- }
- return list
-};
-
-Minimatch.prototype.match = match;
-function match (f, partial) {
- this.debug('match', f, this.pattern);
- // short-circuit in the case of busted things.
- // comments, etc.
- if (this.comment) return false
- if (this.empty) return f === ''
-
- if (f === '/' && partial) return true
-
- var options = this.options;
-
- // windows: need to use /, not \
- if (path.sep !== '/') {
- f = f.split(path.sep).join('/');
- }
-
- // treat the test path as a set of pathparts.
- f = f.split(slashSplit);
- this.debug(this.pattern, 'split', f);
-
- // just ONE of the pattern sets in this.set needs to match
- // in order for it to be valid. If negating, then just one
- // match means that we have failed.
- // Either way, return on the first hit.
-
- var set = this.set;
- this.debug(this.pattern, 'set', set);
-
- // Find the basename of the path by looking for the last non-empty segment
- var filename;
- var i;
- for (i = f.length - 1; i >= 0; i--) {
- filename = f[i];
- if (filename) break
- }
-
- for (i = 0; i < set.length; i++) {
- var pattern = set[i];
- var file = f;
- if (options.matchBase && pattern.length === 1) {
- file = [filename];
- }
- var hit = this.matchOne(file, pattern, partial);
- if (hit) {
- if (options.flipNegate) return true
- return !this.negate
- }
- }
-
- // didn't get any hits. this is success if it's a negative
- // pattern, failure otherwise.
- if (options.flipNegate) return false
- return this.negate
-}
-
-// set partial to true to test if, for example,
-// "/a/b" matches the start of "/*/b/*/d"
-// Partial means, if you run out of file before you run
-// out of pattern, then that's fine, as long as all
-// the parts match.
-Minimatch.prototype.matchOne = function (file, pattern, partial) {
- var options = this.options;
-
- this.debug('matchOne',
- { 'this': this, file: file, pattern: pattern });
-
- this.debug('matchOne', file.length, pattern.length);
-
- for (var fi = 0,
- pi = 0,
- fl = file.length,
- pl = pattern.length
- ; (fi < fl) && (pi < pl)
- ; fi++, pi++) {
- this.debug('matchOne loop');
- var p = pattern[pi];
- var f = file[fi];
-
- this.debug(pattern, p, f);
-
- // should be impossible.
- // some invalid regexp stuff in the set.
- if (p === false) return false
-
- if (p === GLOBSTAR) {
- this.debug('GLOBSTAR', [pattern, p, f]);
-
- // "**"
- // a/**/b/**/c would match the following:
- // a/b/x/y/z/c
- // a/x/y/z/b/c
- // a/b/x/b/x/c
- // a/b/c
- // To do this, take the rest of the pattern after
- // the **, and see if it would match the file remainder.
- // If so, return success.
- // If not, the ** "swallows" a segment, and try again.
- // This is recursively awful.
- //
- // a/**/b/**/c matching a/b/x/y/z/c
- // - a matches a
- // - doublestar
- // - matchOne(b/x/y/z/c, b/**/c)
- // - b matches b
- // - doublestar
- // - matchOne(x/y/z/c, c) -> no
- // - matchOne(y/z/c, c) -> no
- // - matchOne(z/c, c) -> no
- // - matchOne(c, c) yes, hit
- var fr = fi;
- var pr = pi + 1;
- if (pr === pl) {
- this.debug('** at the end');
- // a ** at the end will just swallow the rest.
- // We have found a match.
- // however, it will not swallow /.x, unless
- // options.dot is set.
- // . and .. are *never* matched by **, for explosively
- // exponential reasons.
- for (; fi < fl; fi++) {
- if (file[fi] === '.' || file[fi] === '..' ||
- (!options.dot && file[fi].charAt(0) === '.')) return false
- }
- return true
- }
-
- // ok, let's see if we can swallow whatever we can.
- while (fr < fl) {
- var swallowee = file[fr];
-
- this.debug('\nglobstar while', file, fr, pattern, pr, swallowee);
-
- // XXX remove this slice. Just pass the start index.
- if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
- this.debug('globstar found match!', fr, fl, swallowee);
- // found a match.
- return true
- } else {
- // can't swallow "." or ".." ever.
- // can only swallow ".foo" when explicitly asked.
- if (swallowee === '.' || swallowee === '..' ||
- (!options.dot && swallowee.charAt(0) === '.')) {
- this.debug('dot detected!', file, fr, pattern, pr);
- break
- }
-
- // ** swallows a segment, and continue.
- this.debug('globstar swallow a segment, and continue');
- fr++;
- }
- }
-
- // no match was found.
- // However, in partial mode, we can't say this is necessarily over.
- // If there's more *pattern* left, then
- if (partial) {
- // ran out of file
- this.debug('\n>>> no match, partial?', file, fr, pattern, pr);
- if (fr === fl) return true
- }
- return false
- }
-
- // something other than **
- // non-magic patterns just have to match exactly
- // patterns with magic have been turned into regexps.
- var hit;
- if (typeof p === 'string') {
- if (options.nocase) {
- hit = f.toLowerCase() === p.toLowerCase();
- } else {
- hit = f === p;
- }
- this.debug('string match', p, f, hit);
- } else {
- hit = f.match(p);
- this.debug('pattern match', p, f, hit);
- }
-
- if (!hit) return false
- }
-
- // Note: ending in / means that we'll get a final ""
- // at the end of the pattern. This can only match a
- // corresponding "" at the end of the file.
- // If the file ends in /, then it can only match a
- // a pattern that ends in /, unless the pattern just
- // doesn't have any more for it. But, a/b/ should *not*
- // match "a/b/*", even though "" matches against the
- // [^/]*? pattern, except in partial mode, where it might
- // simply not be reached yet.
- // However, a/b/ should still satisfy a/*
-
- // now either we fell off the end of the pattern, or we're done.
- if (fi === fl && pi === pl) {
- // ran out of pattern and filename at the same time.
- // an exact hit!
- return true
- } else if (fi === fl) {
- // ran out of file, but still had pattern left.
- // this is ok if we're doing the match as part of
- // a glob fs traversal.
- return partial
- } else if (pi === pl) {
- // ran out of pattern, still have file left.
- // this is only acceptable if we're on the very last
- // empty segment of a file with a trailing slash.
- // a/* should match a/b/
- var emptyFileEnd = (fi === fl - 1) && (file[fi] === '');
- return emptyFileEnd
- }
-
- // should be unreachable.
- throw new Error('wtf?')
-};
-
-// replace stuff like \* with *
-function globUnescape (s) {
- return s.replace(/\\(.)/g, '$1')
-}
-
-function regExpEscape (s) {
- return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
-}
-
-function createCommonjsModule(fn, module) {
- return module = { exports: {} }, fn(module, module.exports), module.exports;
-}
-
-var inherits_browser = createCommonjsModule(function (module) {
-if (typeof Object.create === 'function') {
- // implementation from standard node.js 'util' module
- module.exports = function inherits(ctor, superCtor) {
- if (superCtor) {
- ctor.super_ = superCtor;
- ctor.prototype = Object.create(superCtor.prototype, {
- constructor: {
- value: ctor,
- enumerable: false,
- writable: true,
- configurable: true
- }
- });
- }
- };
-} else {
- // old school shim for old browsers
- module.exports = function inherits(ctor, superCtor) {
- if (superCtor) {
- ctor.super_ = superCtor;
- var TempCtor = function () {};
- TempCtor.prototype = superCtor.prototype;
- ctor.prototype = new TempCtor();
- ctor.prototype.constructor = ctor;
- }
- };
-}
-});
-
-var inherits = createCommonjsModule(function (module) {
-try {
- var util = util__default['default'];
- /* istanbul ignore next */
- if (typeof util.inherits !== 'function') throw '';
- module.exports = util.inherits;
-} catch (e) {
- /* istanbul ignore next */
- module.exports = inherits_browser;
-}
-});
-
-function posix(path) {
- return path.charAt(0) === '/';
-}
-
-function win32(path) {
- // https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
- var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
- var result = splitDeviceRe.exec(path);
- var device = result[1] || '';
- var isUnc = Boolean(device && device.charAt(1) !== ':');
-
- // UNC paths are always absolute
- return Boolean(result[2] || isUnc);
-}
-
-var pathIsAbsolute = process.platform === 'win32' ? win32 : posix;
-var posix_1 = posix;
-var win32_1 = win32;
-pathIsAbsolute.posix = posix_1;
-pathIsAbsolute.win32 = win32_1;
-
-var alphasort_1 = alphasort;
-var alphasorti_1 = alphasorti;
-var setopts_1 = setopts;
-var ownProp_1 = ownProp;
-var makeAbs_1 = makeAbs;
-var finish_1 = finish;
-var mark_1 = mark;
-var isIgnored_1 = isIgnored;
-var childrenIgnored_1 = childrenIgnored;
-
-function ownProp (obj, field) {
- return Object.prototype.hasOwnProperty.call(obj, field)
-}
-
-
-
-
-var Minimatch$1 = minimatch_1.Minimatch;
-
-function alphasorti (a, b) {
- return a.toLowerCase().localeCompare(b.toLowerCase())
-}
-
-function alphasort (a, b) {
- return a.localeCompare(b)
-}
-
-function setupIgnores (self, options) {
- self.ignore = options.ignore || [];
-
- if (!Array.isArray(self.ignore))
- self.ignore = [self.ignore];
-
- if (self.ignore.length) {
- self.ignore = self.ignore.map(ignoreMap);
- }
-}
-
-// ignore patterns are always in dot:true mode.
-function ignoreMap (pattern) {
- var gmatcher = null;
- if (pattern.slice(-3) === '/**') {
- var gpattern = pattern.replace(/(\/\*\*)+$/, '');
- gmatcher = new Minimatch$1(gpattern, { dot: true });
- }
-
- return {
- matcher: new Minimatch$1(pattern, { dot: true }),
- gmatcher: gmatcher
- }
-}
-
-function setopts (self, pattern, options) {
- if (!options)
- options = {};
-
- // base-matching: just use globstar for that.
- if (options.matchBase && -1 === pattern.indexOf("/")) {
- if (options.noglobstar) {
- throw new Error("base matching requires globstar")
- }
- pattern = "**/" + pattern;
- }
-
- self.silent = !!options.silent;
- self.pattern = pattern;
- self.strict = options.strict !== false;
- self.realpath = !!options.realpath;
- self.realpathCache = options.realpathCache || Object.create(null);
- self.follow = !!options.follow;
- self.dot = !!options.dot;
- self.mark = !!options.mark;
- self.nodir = !!options.nodir;
- if (self.nodir)
- self.mark = true;
- self.sync = !!options.sync;
- self.nounique = !!options.nounique;
- self.nonull = !!options.nonull;
- self.nosort = !!options.nosort;
- self.nocase = !!options.nocase;
- self.stat = !!options.stat;
- self.noprocess = !!options.noprocess;
- self.absolute = !!options.absolute;
-
- self.maxLength = options.maxLength || Infinity;
- self.cache = options.cache || Object.create(null);
- self.statCache = options.statCache || Object.create(null);
- self.symlinks = options.symlinks || Object.create(null);
-
- setupIgnores(self, options);
-
- self.changedCwd = false;
- var cwd = process.cwd();
- if (!ownProp(options, "cwd"))
- self.cwd = cwd;
- else {
- self.cwd = path__default['default'].resolve(options.cwd);
- self.changedCwd = self.cwd !== cwd;
- }
-
- self.root = options.root || path__default['default'].resolve(self.cwd, "/");
- self.root = path__default['default'].resolve(self.root);
- if (process.platform === "win32")
- self.root = self.root.replace(/\\/g, "/");
-
- // TODO: is an absolute `cwd` supposed to be resolved against `root`?
- // e.g. { cwd: '/test', root: __dirname } === path.join(__dirname, '/test')
- self.cwdAbs = pathIsAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd);
- if (process.platform === "win32")
- self.cwdAbs = self.cwdAbs.replace(/\\/g, "/");
- self.nomount = !!options.nomount;
-
- // disable comments and negation in Minimatch.
- // Note that they are not supported in Glob itself anyway.
- options.nonegate = true;
- options.nocomment = true;
-
- self.minimatch = new Minimatch$1(pattern, options);
- self.options = self.minimatch.options;
-}
-
-function finish (self) {
- var nou = self.nounique;
- var all = nou ? [] : Object.create(null);
-
- for (var i = 0, l = self.matches.length; i < l; i ++) {
- var matches = self.matches[i];
- if (!matches || Object.keys(matches).length === 0) {
- if (self.nonull) {
- // do like the shell, and spit out the literal glob
- var literal = self.minimatch.globSet[i];
- if (nou)
- all.push(literal);
- else
- all[literal] = true;
- }
- } else {
- // had matches
- var m = Object.keys(matches);
- if (nou)
- all.push.apply(all, m);
- else
- m.forEach(function (m) {
- all[m] = true;
- });
- }
- }
-
- if (!nou)
- all = Object.keys(all);
-
- if (!self.nosort)
- all = all.sort(self.nocase ? alphasorti : alphasort);
-
- // at *some* point we statted all of these
- if (self.mark) {
- for (var i = 0; i < all.length; i++) {
- all[i] = self._mark(all[i]);
- }
- if (self.nodir) {
- all = all.filter(function (e) {
- var notDir = !(/\/$/.test(e));
- var c = self.cache[e] || self.cache[makeAbs(self, e)];
- if (notDir && c)
- notDir = c !== 'DIR' && !Array.isArray(c);
- return notDir
- });
- }
- }
-
- if (self.ignore.length)
- all = all.filter(function(m) {
- return !isIgnored(self, m)
- });
-
- self.found = all;
-}
-
-function mark (self, p) {
- var abs = makeAbs(self, p);
- var c = self.cache[abs];
- var m = p;
- if (c) {
- var isDir = c === 'DIR' || Array.isArray(c);
- var slash = p.slice(-1) === '/';
-
- if (isDir && !slash)
- m += '/';
- else if (!isDir && slash)
- m = m.slice(0, -1);
-
- if (m !== p) {
- var mabs = makeAbs(self, m);
- self.statCache[mabs] = self.statCache[abs];
- self.cache[mabs] = self.cache[abs];
- }
- }
-
- return m
-}
-
-// lotta situps...
-function makeAbs (self, f) {
- var abs = f;
- if (f.charAt(0) === '/') {
- abs = path__default['default'].join(self.root, f);
- } else if (pathIsAbsolute(f) || f === '') {
- abs = f;
- } else if (self.changedCwd) {
- abs = path__default['default'].resolve(self.cwd, f);
- } else {
- abs = path__default['default'].resolve(f);
- }
-
- if (process.platform === 'win32')
- abs = abs.replace(/\\/g, '/');
-
- return abs
-}
-
-
-// Return true, if pattern ends with globstar '**', for the accompanying parent directory.
-// Ex:- If node_modules/** is the pattern, add 'node_modules' to ignore list along with it's contents
-function isIgnored (self, path) {
- if (!self.ignore.length)
- return false
-
- return self.ignore.some(function(item) {
- return item.matcher.match(path) || !!(item.gmatcher && item.gmatcher.match(path))
- })
-}
-
-function childrenIgnored (self, path) {
- if (!self.ignore.length)
- return false
-
- return self.ignore.some(function(item) {
- return !!(item.gmatcher && item.gmatcher.match(path))
- })
-}
-
-var common = {
- alphasort: alphasort_1,
- alphasorti: alphasorti_1,
- setopts: setopts_1,
- ownProp: ownProp_1,
- makeAbs: makeAbs_1,
- finish: finish_1,
- mark: mark_1,
- isIgnored: isIgnored_1,
- childrenIgnored: childrenIgnored_1
-};
-
-var sync = globSync;
-globSync.GlobSync = GlobSync;
-var setopts$1 = common.setopts;
-var ownProp$1 = common.ownProp;
-var childrenIgnored$1 = common.childrenIgnored;
-var isIgnored$1 = common.isIgnored;
-
-function globSync (pattern, options) {
- if (typeof options === 'function' || arguments.length === 3)
- throw new TypeError('callback provided to sync glob\n'+
- 'See: https://github.com/isaacs/node-glob/issues/167')
-
- return new GlobSync(pattern, options).found
-}
-
-function GlobSync (pattern, options) {
- if (!pattern)
- throw new Error('must provide pattern')
-
- if (typeof options === 'function' || arguments.length === 3)
- throw new TypeError('callback provided to sync glob\n'+
- 'See: https://github.com/isaacs/node-glob/issues/167')
-
- if (!(this instanceof GlobSync))
- return new GlobSync(pattern, options)
-
- setopts$1(this, pattern, options);
-
- if (this.noprocess)
- return this
-
- var n = this.minimatch.set.length;
- this.matches = new Array(n);
- for (var i = 0; i < n; i ++) {
- this._process(this.minimatch.set[i], i, false);
- }
- this._finish();
-}
-
-GlobSync.prototype._finish = function () {
- assert__default['default'](this instanceof GlobSync);
- if (this.realpath) {
- var self = this;
- this.matches.forEach(function (matchset, index) {
- var set = self.matches[index] = Object.create(null);
- for (var p in matchset) {
- try {
- p = self._makeAbs(p);
- var real = fs_realpath.realpathSync(p, self.realpathCache);
- set[real] = true;
- } catch (er) {
- if (er.syscall === 'stat')
- set[self._makeAbs(p)] = true;
- else
- throw er
- }
- }
- });
- }
- common.finish(this);
-};
-
-
-GlobSync.prototype._process = function (pattern, index, inGlobStar) {
- assert__default['default'](this instanceof GlobSync);
-
- // Get the first [n] parts of pattern that are all strings.
- var n = 0;
- while (typeof pattern[n] === 'string') {
- n ++;
- }
- // now n is the index of the first one that is *not* a string.
-
- // See if there's anything else
- var prefix;
- switch (n) {
- // if not, then this is rather simple
- case pattern.length:
- this._processSimple(pattern.join('/'), index);
- return
-
- case 0:
- // pattern *starts* with some non-trivial item.
- // going to readdir(cwd), but not include the prefix in matches.
- prefix = null;
- break
-
- default:
- // pattern has some string bits in the front.
- // whatever it starts with, whether that's 'absolute' like /foo/bar,
- // or 'relative' like '../baz'
- prefix = pattern.slice(0, n).join('/');
- break
- }
-
- var remain = pattern.slice(n);
-
- // get the list of entries.
- var read;
- if (prefix === null)
- read = '.';
- else if (pathIsAbsolute(prefix) || pathIsAbsolute(pattern.join('/'))) {
- if (!prefix || !pathIsAbsolute(prefix))
- prefix = '/' + prefix;
- read = prefix;
- } else
- read = prefix;
-
- var abs = this._makeAbs(read);
-
- //if ignored, skip processing
- if (childrenIgnored$1(this, read))
- return
-
- var isGlobStar = remain[0] === minimatch_1.GLOBSTAR;
- if (isGlobStar)
- this._processGlobStar(prefix, read, abs, remain, index, inGlobStar);
- else
- this._processReaddir(prefix, read, abs, remain, index, inGlobStar);
-};
-
-
-GlobSync.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar) {
- var entries = this._readdir(abs, inGlobStar);
-
- // if the abs isn't a dir, then nothing can match!
- if (!entries)
- return
-
- // It will only match dot entries if it starts with a dot, or if
- // dot is set. Stuff like @(.foo|.bar) isn't allowed.
- var pn = remain[0];
- var negate = !!this.minimatch.negate;
- var rawGlob = pn._glob;
- var dotOk = this.dot || rawGlob.charAt(0) === '.';
-
- var matchedEntries = [];
- for (var i = 0; i < entries.length; i++) {
- var e = entries[i];
- if (e.charAt(0) !== '.' || dotOk) {
- var m;
- if (negate && !prefix) {
- m = !e.match(pn);
- } else {
- m = e.match(pn);
- }
- if (m)
- matchedEntries.push(e);
- }
- }
-
- var len = matchedEntries.length;
- // If there are no matched entries, then nothing matches.
- if (len === 0)
- return
-
- // if this is the last remaining pattern bit, then no need for
- // an additional stat *unless* the user has specified mark or
- // stat explicitly. We know they exist, since readdir returned
- // them.
-
- if (remain.length === 1 && !this.mark && !this.stat) {
- if (!this.matches[index])
- this.matches[index] = Object.create(null);
-
- for (var i = 0; i < len; i ++) {
- var e = matchedEntries[i];
- if (prefix) {
- if (prefix.slice(-1) !== '/')
- e = prefix + '/' + e;
- else
- e = prefix + e;
- }
-
- if (e.charAt(0) === '/' && !this.nomount) {
- e = path__default['default'].join(this.root, e);
- }
- this._emitMatch(index, e);
- }
- // This was the last one, and no stats were needed
- return
- }
-
- // now test all matched entries as stand-ins for that part
- // of the pattern.
- remain.shift();
- for (var i = 0; i < len; i ++) {
- var e = matchedEntries[i];
- var newPattern;
- if (prefix)
- newPattern = [prefix, e];
- else
- newPattern = [e];
- this._process(newPattern.concat(remain), index, inGlobStar);
- }
-};
-
-
-GlobSync.prototype._emitMatch = function (index, e) {
- if (isIgnored$1(this, e))
- return
-
- var abs = this._makeAbs(e);
-
- if (this.mark)
- e = this._mark(e);
-
- if (this.absolute) {
- e = abs;
- }
-
- if (this.matches[index][e])
- return
-
- if (this.nodir) {
- var c = this.cache[abs];
- if (c === 'DIR' || Array.isArray(c))
- return
- }
-
- this.matches[index][e] = true;
-
- if (this.stat)
- this._stat(e);
-};
-
-
-GlobSync.prototype._readdirInGlobStar = function (abs) {
- // follow all symlinked directories forever
- // just proceed as if this is a non-globstar situation
- if (this.follow)
- return this._readdir(abs, false)
-
- var entries;
- var lstat;
- try {
- lstat = fs__default['default'].lstatSync(abs);
- } catch (er) {
- if (er.code === 'ENOENT') {
- // lstat failed, doesn't exist
- return null
- }
- }
-
- var isSym = lstat && lstat.isSymbolicLink();
- this.symlinks[abs] = isSym;
-
- // If it's not a symlink or a dir, then it's definitely a regular file.
- // don't bother doing a readdir in that case.
- if (!isSym && lstat && !lstat.isDirectory())
- this.cache[abs] = 'FILE';
- else
- entries = this._readdir(abs, false);
-
- return entries
-};
-
-GlobSync.prototype._readdir = function (abs, inGlobStar) {
-
- if (inGlobStar && !ownProp$1(this.symlinks, abs))
- return this._readdirInGlobStar(abs)
-
- if (ownProp$1(this.cache, abs)) {
- var c = this.cache[abs];
- if (!c || c === 'FILE')
- return null
-
- if (Array.isArray(c))
- return c
- }
-
- try {
- return this._readdirEntries(abs, fs__default['default'].readdirSync(abs))
- } catch (er) {
- this._readdirError(abs, er);
- return null
- }
-};
-
-GlobSync.prototype._readdirEntries = function (abs, entries) {
- // if we haven't asked to stat everything, then just
- // assume that everything in there exists, so we can avoid
- // having to stat it a second time.
- if (!this.mark && !this.stat) {
- for (var i = 0; i < entries.length; i ++) {
- var e = entries[i];
- if (abs === '/')
- e = abs + e;
- else
- e = abs + '/' + e;
- this.cache[e] = true;
- }
- }
-
- this.cache[abs] = entries;
-
- // mark and cache dir-ness
- return entries
-};
-
-GlobSync.prototype._readdirError = function (f, er) {
- // handle errors, and cache the information
- switch (er.code) {
- case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
- case 'ENOTDIR': // totally normal. means it *does* exist.
- var abs = this._makeAbs(f);
- this.cache[abs] = 'FILE';
- if (abs === this.cwdAbs) {
- var error = new Error(er.code + ' invalid cwd ' + this.cwd);
- error.path = this.cwd;
- error.code = er.code;
- throw error
- }
- break
-
- case 'ENOENT': // not terribly unusual
- case 'ELOOP':
- case 'ENAMETOOLONG':
- case 'UNKNOWN':
- this.cache[this._makeAbs(f)] = false;
- break
-
- default: // some unusual error. Treat as failure.
- this.cache[this._makeAbs(f)] = false;
- if (this.strict)
- throw er
- if (!this.silent)
- console.error('glob error', er);
- break
- }
-};
-
-GlobSync.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar) {
-
- var entries = this._readdir(abs, inGlobStar);
-
- // no entries means not a dir, so it can never have matches
- // foo.txt/** doesn't match foo.txt
- if (!entries)
- return
-
- // test without the globstar, and with every child both below
- // and replacing the globstar.
- var remainWithoutGlobStar = remain.slice(1);
- var gspref = prefix ? [ prefix ] : [];
- var noGlobStar = gspref.concat(remainWithoutGlobStar);
-
- // the noGlobStar pattern exits the inGlobStar state
- this._process(noGlobStar, index, false);
-
- var len = entries.length;
- var isSym = this.symlinks[abs];
-
- // If it's a symlink, and we're in a globstar, then stop
- if (isSym && inGlobStar)
- return
-
- for (var i = 0; i < len; i++) {
- var e = entries[i];
- if (e.charAt(0) === '.' && !this.dot)
- continue
-
- // these two cases enter the inGlobStar state
- var instead = gspref.concat(entries[i], remainWithoutGlobStar);
- this._process(instead, index, true);
-
- var below = gspref.concat(entries[i], remain);
- this._process(below, index, true);
- }
-};
-
-GlobSync.prototype._processSimple = function (prefix, index) {
- // XXX review this. Shouldn't it be doing the mounting etc
- // before doing stat? kinda weird?
- var exists = this._stat(prefix);
-
- if (!this.matches[index])
- this.matches[index] = Object.create(null);
-
- // If it doesn't exist, then just mark the lack of results
- if (!exists)
- return
-
- if (prefix && pathIsAbsolute(prefix) && !this.nomount) {
- var trail = /[\/\\]$/.test(prefix);
- if (prefix.charAt(0) === '/') {
- prefix = path__default['default'].join(this.root, prefix);
- } else {
- prefix = path__default['default'].resolve(this.root, prefix);
- if (trail)
- prefix += '/';
- }
- }
-
- if (process.platform === 'win32')
- prefix = prefix.replace(/\\/g, '/');
-
- // Mark this as a match
- this._emitMatch(index, prefix);
-};
-
-// Returns either 'DIR', 'FILE', or false
-GlobSync.prototype._stat = function (f) {
- var abs = this._makeAbs(f);
- var needDir = f.slice(-1) === '/';
-
- if (f.length > this.maxLength)
- return false
-
- if (!this.stat && ownProp$1(this.cache, abs)) {
- var c = this.cache[abs];
-
- if (Array.isArray(c))
- c = 'DIR';
-
- // It exists, but maybe not how we need it
- if (!needDir || c === 'DIR')
- return c
-
- if (needDir && c === 'FILE')
- return false
-
- // otherwise we have to stat, because maybe c=true
- // if we know it exists, but not what it is.
- }
- var stat = this.statCache[abs];
- if (!stat) {
- var lstat;
- try {
- lstat = fs__default['default'].lstatSync(abs);
- } catch (er) {
- if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
- this.statCache[abs] = false;
- return false
- }
- }
-
- if (lstat && lstat.isSymbolicLink()) {
- try {
- stat = fs__default['default'].statSync(abs);
- } catch (er) {
- stat = lstat;
- }
- } else {
- stat = lstat;
- }
- }
-
- this.statCache[abs] = stat;
-
- var c = true;
- if (stat)
- c = stat.isDirectory() ? 'DIR' : 'FILE';
-
- this.cache[abs] = this.cache[abs] || c;
-
- if (needDir && c === 'FILE')
- return false
-
- return c
-};
-
-GlobSync.prototype._mark = function (p) {
- return common.mark(this, p)
-};
-
-GlobSync.prototype._makeAbs = function (f) {
- return common.makeAbs(this, f)
-};
-
-// Returns a wrapper function that returns a wrapped callback
-// The wrapper function should do some stuff, and return a
-// presumably different callback function.
-// This makes sure that own properties are retained, so that
-// decorations and such are not lost along the way.
-var wrappy_1 = wrappy;
-function wrappy (fn, cb) {
- if (fn && cb) return wrappy(fn)(cb)
-
- if (typeof fn !== 'function')
- throw new TypeError('need wrapper function')
-
- Object.keys(fn).forEach(function (k) {
- wrapper[k] = fn[k];
- });
-
- return wrapper
-
- function wrapper() {
- var args = new Array(arguments.length);
- for (var i = 0; i < args.length; i++) {
- args[i] = arguments[i];
- }
- var ret = fn.apply(this, args);
- var cb = args[args.length-1];
- if (typeof ret === 'function' && ret !== cb) {
- Object.keys(cb).forEach(function (k) {
- ret[k] = cb[k];
- });
- }
- return ret
- }
-}
-
-var once_1 = wrappy_1(once);
-var strict = wrappy_1(onceStrict);
-
-once.proto = once(function () {
- Object.defineProperty(Function.prototype, 'once', {
- value: function () {
- return once(this)
- },
- configurable: true
- });
-
- Object.defineProperty(Function.prototype, 'onceStrict', {
- value: function () {
- return onceStrict(this)
- },
- configurable: true
- });
-});
-
-function once (fn) {
- var f = function () {
- if (f.called) return f.value
- f.called = true;
- return f.value = fn.apply(this, arguments)
- };
- f.called = false;
- return f
-}
-
-function onceStrict (fn) {
- var f = function () {
- if (f.called)
- throw new Error(f.onceError)
- f.called = true;
- return f.value = fn.apply(this, arguments)
- };
- var name = fn.name || 'Function wrapped with `once`';
- f.onceError = name + " shouldn't be called more than once";
- f.called = false;
- return f
-}
-once_1.strict = strict;
-
-var reqs = Object.create(null);
-
-
-var inflight_1 = wrappy_1(inflight);
-
-function inflight (key, cb) {
- if (reqs[key]) {
- reqs[key].push(cb);
- return null
- } else {
- reqs[key] = [cb];
- return makeres(key)
- }
-}
-
-function makeres (key) {
- return once_1(function RES () {
- var cbs = reqs[key];
- var len = cbs.length;
- var args = slice(arguments);
-
- // XXX It's somewhat ambiguous whether a new callback added in this
- // pass should be queued for later execution if something in the
- // list of callbacks throws, or if it should just be discarded.
- // However, it's such an edge case that it hardly matters, and either
- // choice is likely as surprising as the other.
- // As it happens, we do go ahead and schedule it for later execution.
- try {
- for (var i = 0; i < len; i++) {
- cbs[i].apply(null, args);
- }
- } finally {
- if (cbs.length > len) {
- // added more in the interim.
- // de-zalgo, just in case, but don't call again.
- cbs.splice(0, len);
- process.nextTick(function () {
- RES.apply(null, args);
- });
- } else {
- delete reqs[key];
- }
- }
- })
-}
-
-function slice (args) {
- var length = args.length;
- var array = [];
-
- for (var i = 0; i < length; i++) array[i] = args[i];
- return array
-}
-
-// Approach:
-//
-// 1. Get the minimatch set
-// 2. For each pattern in the set, PROCESS(pattern, false)
-// 3. Store matches per-set, then uniq them
-//
-// PROCESS(pattern, inGlobStar)
-// Get the first [n] items from pattern that are all strings
-// Join these together. This is PREFIX.
-// If there is no more remaining, then stat(PREFIX) and
-// add to matches if it succeeds. END.
-//
-// If inGlobStar and PREFIX is symlink and points to dir
-// set ENTRIES = []
-// else readdir(PREFIX) as ENTRIES
-// If fail, END
-//
-// with ENTRIES
-// If pattern[n] is GLOBSTAR
-// // handle the case where the globstar match is empty
-// // by pruning it out, and testing the resulting pattern
-// PROCESS(pattern[0..n] + pattern[n+1 .. $], false)
-// // handle other cases.
-// for ENTRY in ENTRIES (not dotfiles)
-// // attach globstar + tail onto the entry
-// // Mark that this entry is a globstar match
-// PROCESS(pattern[0..n] + ENTRY + pattern[n .. $], true)
-//
-// else // not globstar
-// for ENTRY in ENTRIES (not dotfiles, unless pattern[n] is dot)
-// Test ENTRY against pattern[n]
-// If fails, continue
-// If passes, PROCESS(pattern[0..n] + item + pattern[n+1 .. $])
-//
-// Caveat:
-// Cache all stats and readdirs results to minimize syscall. Since all
-// we ever care about is existence and directory-ness, we can just keep
-// `true` for files, and [children,...] for directories, or `false` for
-// things that don't exist.
-
-var glob_1 = glob;
-
-var EE = events__default['default'].EventEmitter;
-var setopts$2 = common.setopts;
-var ownProp$2 = common.ownProp;
-
-
-var childrenIgnored$2 = common.childrenIgnored;
-var isIgnored$2 = common.isIgnored;
-
-
-
-function glob (pattern, options, cb) {
- if (typeof options === 'function') cb = options, options = {};
- if (!options) options = {};
-
- if (options.sync) {
- if (cb)
- throw new TypeError('callback provided to sync glob')
- return sync(pattern, options)
- }
-
- return new Glob(pattern, options, cb)
-}
-
-glob.sync = sync;
-var GlobSync$1 = glob.GlobSync = sync.GlobSync;
-
-// old api surface
-glob.glob = glob;
-
-function extend (origin, add) {
- if (add === null || typeof add !== 'object') {
- return origin
- }
-
- var keys = Object.keys(add);
- var i = keys.length;
- while (i--) {
- origin[keys[i]] = add[keys[i]];
- }
- return origin
-}
-
-glob.hasMagic = function (pattern, options_) {
- var options = extend({}, options_);
- options.noprocess = true;
-
- var g = new Glob(pattern, options);
- var set = g.minimatch.set;
-
- if (!pattern)
- return false
-
- if (set.length > 1)
- return true
-
- for (var j = 0; j < set[0].length; j++) {
- if (typeof set[0][j] !== 'string')
- return true
- }
-
- return false
-};
-
-glob.Glob = Glob;
-inherits(Glob, EE);
-function Glob (pattern, options, cb) {
- if (typeof options === 'function') {
- cb = options;
- options = null;
- }
-
- if (options && options.sync) {
- if (cb)
- throw new TypeError('callback provided to sync glob')
- return new GlobSync$1(pattern, options)
- }
-
- if (!(this instanceof Glob))
- return new Glob(pattern, options, cb)
-
- setopts$2(this, pattern, options);
- this._didRealPath = false;
-
- // process each pattern in the minimatch set
- var n = this.minimatch.set.length;
-
- // The matches are stored as {: true,...} so that
- // duplicates are automagically pruned.
- // Later, we do an Object.keys() on these.
- // Keep them as a list so we can fill in when nonull is set.
- this.matches = new Array(n);
-
- if (typeof cb === 'function') {
- cb = once_1(cb);
- this.on('error', cb);
- this.on('end', function (matches) {
- cb(null, matches);
- });
- }
-
- var self = this;
- this._processing = 0;
-
- this._emitQueue = [];
- this._processQueue = [];
- this.paused = false;
-
- if (this.noprocess)
- return this
-
- if (n === 0)
- return done()
-
- var sync = true;
- for (var i = 0; i < n; i ++) {
- this._process(this.minimatch.set[i], i, false, done);
- }
- sync = false;
-
- function done () {
- --self._processing;
- if (self._processing <= 0) {
- if (sync) {
- process.nextTick(function () {
- self._finish();
- });
- } else {
- self._finish();
- }
- }
- }
-}
-
-Glob.prototype._finish = function () {
- assert__default['default'](this instanceof Glob);
- if (this.aborted)
- return
-
- if (this.realpath && !this._didRealpath)
- return this._realpath()
-
- common.finish(this);
- this.emit('end', this.found);
-};
-
-Glob.prototype._realpath = function () {
- if (this._didRealpath)
- return
-
- this._didRealpath = true;
-
- var n = this.matches.length;
- if (n === 0)
- return this._finish()
-
- var self = this;
- for (var i = 0; i < this.matches.length; i++)
- this._realpathSet(i, next);
-
- function next () {
- if (--n === 0)
- self._finish();
- }
-};
-
-Glob.prototype._realpathSet = function (index, cb) {
- var matchset = this.matches[index];
- if (!matchset)
- return cb()
-
- var found = Object.keys(matchset);
- var self = this;
- var n = found.length;
-
- if (n === 0)
- return cb()
-
- var set = this.matches[index] = Object.create(null);
- found.forEach(function (p, i) {
- // If there's a problem with the stat, then it means that
- // one or more of the links in the realpath couldn't be
- // resolved. just return the abs value in that case.
- p = self._makeAbs(p);
- fs_realpath.realpath(p, self.realpathCache, function (er, real) {
- if (!er)
- set[real] = true;
- else if (er.syscall === 'stat')
- set[p] = true;
- else
- self.emit('error', er); // srsly wtf right here
-
- if (--n === 0) {
- self.matches[index] = set;
- cb();
- }
- });
- });
-};
-
-Glob.prototype._mark = function (p) {
- return common.mark(this, p)
-};
-
-Glob.prototype._makeAbs = function (f) {
- return common.makeAbs(this, f)
-};
-
-Glob.prototype.abort = function () {
- this.aborted = true;
- this.emit('abort');
-};
-
-Glob.prototype.pause = function () {
- if (!this.paused) {
- this.paused = true;
- this.emit('pause');
- }
-};
-
-Glob.prototype.resume = function () {
- if (this.paused) {
- this.emit('resume');
- this.paused = false;
- if (this._emitQueue.length) {
- var eq = this._emitQueue.slice(0);
- this._emitQueue.length = 0;
- for (var i = 0; i < eq.length; i ++) {
- var e = eq[i];
- this._emitMatch(e[0], e[1]);
- }
- }
- if (this._processQueue.length) {
- var pq = this._processQueue.slice(0);
- this._processQueue.length = 0;
- for (var i = 0; i < pq.length; i ++) {
- var p = pq[i];
- this._processing--;
- this._process(p[0], p[1], p[2], p[3]);
- }
- }
- }
-};
-
-Glob.prototype._process = function (pattern, index, inGlobStar, cb) {
- assert__default['default'](this instanceof Glob);
- assert__default['default'](typeof cb === 'function');
-
- if (this.aborted)
- return
-
- this._processing++;
- if (this.paused) {
- this._processQueue.push([pattern, index, inGlobStar, cb]);
- return
- }
-
- //console.error('PROCESS %d', this._processing, pattern)
-
- // Get the first [n] parts of pattern that are all strings.
- var n = 0;
- while (typeof pattern[n] === 'string') {
- n ++;
- }
- // now n is the index of the first one that is *not* a string.
-
- // see if there's anything else
- var prefix;
- switch (n) {
- // if not, then this is rather simple
- case pattern.length:
- this._processSimple(pattern.join('/'), index, cb);
- return
-
- case 0:
- // pattern *starts* with some non-trivial item.
- // going to readdir(cwd), but not include the prefix in matches.
- prefix = null;
- break
-
- default:
- // pattern has some string bits in the front.
- // whatever it starts with, whether that's 'absolute' like /foo/bar,
- // or 'relative' like '../baz'
- prefix = pattern.slice(0, n).join('/');
- break
- }
-
- var remain = pattern.slice(n);
-
- // get the list of entries.
- var read;
- if (prefix === null)
- read = '.';
- else if (pathIsAbsolute(prefix) || pathIsAbsolute(pattern.join('/'))) {
- if (!prefix || !pathIsAbsolute(prefix))
- prefix = '/' + prefix;
- read = prefix;
- } else
- read = prefix;
-
- var abs = this._makeAbs(read);
-
- //if ignored, skip _processing
- if (childrenIgnored$2(this, read))
- return cb()
-
- var isGlobStar = remain[0] === minimatch_1.GLOBSTAR;
- if (isGlobStar)
- this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb);
- else
- this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb);
-};
-
-Glob.prototype._processReaddir = function (prefix, read, abs, remain, index, inGlobStar, cb) {
- var self = this;
- this._readdir(abs, inGlobStar, function (er, entries) {
- return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb)
- });
-};
-
-Glob.prototype._processReaddir2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
-
- // if the abs isn't a dir, then nothing can match!
- if (!entries)
- return cb()
-
- // It will only match dot entries if it starts with a dot, or if
- // dot is set. Stuff like @(.foo|.bar) isn't allowed.
- var pn = remain[0];
- var negate = !!this.minimatch.negate;
- var rawGlob = pn._glob;
- var dotOk = this.dot || rawGlob.charAt(0) === '.';
-
- var matchedEntries = [];
- for (var i = 0; i < entries.length; i++) {
- var e = entries[i];
- if (e.charAt(0) !== '.' || dotOk) {
- var m;
- if (negate && !prefix) {
- m = !e.match(pn);
- } else {
- m = e.match(pn);
- }
- if (m)
- matchedEntries.push(e);
- }
- }
-
- //console.error('prd2', prefix, entries, remain[0]._glob, matchedEntries)
-
- var len = matchedEntries.length;
- // If there are no matched entries, then nothing matches.
- if (len === 0)
- return cb()
-
- // if this is the last remaining pattern bit, then no need for
- // an additional stat *unless* the user has specified mark or
- // stat explicitly. We know they exist, since readdir returned
- // them.
-
- if (remain.length === 1 && !this.mark && !this.stat) {
- if (!this.matches[index])
- this.matches[index] = Object.create(null);
-
- for (var i = 0; i < len; i ++) {
- var e = matchedEntries[i];
- if (prefix) {
- if (prefix !== '/')
- e = prefix + '/' + e;
- else
- e = prefix + e;
- }
-
- if (e.charAt(0) === '/' && !this.nomount) {
- e = path__default['default'].join(this.root, e);
- }
- this._emitMatch(index, e);
- }
- // This was the last one, and no stats were needed
- return cb()
- }
-
- // now test all matched entries as stand-ins for that part
- // of the pattern.
- remain.shift();
- for (var i = 0; i < len; i ++) {
- var e = matchedEntries[i];
- if (prefix) {
- if (prefix !== '/')
- e = prefix + '/' + e;
- else
- e = prefix + e;
- }
- this._process([e].concat(remain), index, inGlobStar, cb);
- }
- cb();
-};
-
-Glob.prototype._emitMatch = function (index, e) {
- if (this.aborted)
- return
-
- if (isIgnored$2(this, e))
- return
-
- if (this.paused) {
- this._emitQueue.push([index, e]);
- return
- }
-
- var abs = pathIsAbsolute(e) ? e : this._makeAbs(e);
-
- if (this.mark)
- e = this._mark(e);
-
- if (this.absolute)
- e = abs;
-
- if (this.matches[index][e])
- return
-
- if (this.nodir) {
- var c = this.cache[abs];
- if (c === 'DIR' || Array.isArray(c))
- return
- }
-
- this.matches[index][e] = true;
-
- var st = this.statCache[abs];
- if (st)
- this.emit('stat', e, st);
-
- this.emit('match', e);
-};
-
-Glob.prototype._readdirInGlobStar = function (abs, cb) {
- if (this.aborted)
- return
-
- // follow all symlinked directories forever
- // just proceed as if this is a non-globstar situation
- if (this.follow)
- return this._readdir(abs, false, cb)
-
- var lstatkey = 'lstat\0' + abs;
- var self = this;
- var lstatcb = inflight_1(lstatkey, lstatcb_);
-
- if (lstatcb)
- fs__default['default'].lstat(abs, lstatcb);
-
- function lstatcb_ (er, lstat) {
- if (er && er.code === 'ENOENT')
- return cb()
-
- var isSym = lstat && lstat.isSymbolicLink();
- self.symlinks[abs] = isSym;
-
- // If it's not a symlink or a dir, then it's definitely a regular file.
- // don't bother doing a readdir in that case.
- if (!isSym && lstat && !lstat.isDirectory()) {
- self.cache[abs] = 'FILE';
- cb();
- } else
- self._readdir(abs, false, cb);
- }
-};
-
-Glob.prototype._readdir = function (abs, inGlobStar, cb) {
- if (this.aborted)
- return
-
- cb = inflight_1('readdir\0'+abs+'\0'+inGlobStar, cb);
- if (!cb)
- return
-
- //console.error('RD %j %j', +inGlobStar, abs)
- if (inGlobStar && !ownProp$2(this.symlinks, abs))
- return this._readdirInGlobStar(abs, cb)
-
- if (ownProp$2(this.cache, abs)) {
- var c = this.cache[abs];
- if (!c || c === 'FILE')
- return cb()
-
- if (Array.isArray(c))
- return cb(null, c)
- }
- fs__default['default'].readdir(abs, readdirCb(this, abs, cb));
-};
-
-function readdirCb (self, abs, cb) {
- return function (er, entries) {
- if (er)
- self._readdirError(abs, er, cb);
- else
- self._readdirEntries(abs, entries, cb);
- }
-}
-
-Glob.prototype._readdirEntries = function (abs, entries, cb) {
- if (this.aborted)
- return
-
- // if we haven't asked to stat everything, then just
- // assume that everything in there exists, so we can avoid
- // having to stat it a second time.
- if (!this.mark && !this.stat) {
- for (var i = 0; i < entries.length; i ++) {
- var e = entries[i];
- if (abs === '/')
- e = abs + e;
- else
- e = abs + '/' + e;
- this.cache[e] = true;
- }
- }
-
- this.cache[abs] = entries;
- return cb(null, entries)
-};
-
-Glob.prototype._readdirError = function (f, er, cb) {
- if (this.aborted)
- return
-
- // handle errors, and cache the information
- switch (er.code) {
- case 'ENOTSUP': // https://github.com/isaacs/node-glob/issues/205
- case 'ENOTDIR': // totally normal. means it *does* exist.
- var abs = this._makeAbs(f);
- this.cache[abs] = 'FILE';
- if (abs === this.cwdAbs) {
- var error = new Error(er.code + ' invalid cwd ' + this.cwd);
- error.path = this.cwd;
- error.code = er.code;
- this.emit('error', error);
- this.abort();
- }
- break
-
- case 'ENOENT': // not terribly unusual
- case 'ELOOP':
- case 'ENAMETOOLONG':
- case 'UNKNOWN':
- this.cache[this._makeAbs(f)] = false;
- break
-
- default: // some unusual error. Treat as failure.
- this.cache[this._makeAbs(f)] = false;
- if (this.strict) {
- this.emit('error', er);
- // If the error is handled, then we abort
- // if not, we threw out of here
- this.abort();
- }
- if (!this.silent)
- console.error('glob error', er);
- break
- }
-
- return cb()
-};
-
-Glob.prototype._processGlobStar = function (prefix, read, abs, remain, index, inGlobStar, cb) {
- var self = this;
- this._readdir(abs, inGlobStar, function (er, entries) {
- self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb);
- });
-};
-
-
-Glob.prototype._processGlobStar2 = function (prefix, read, abs, remain, index, inGlobStar, entries, cb) {
- //console.error('pgs2', prefix, remain[0], entries)
-
- // no entries means not a dir, so it can never have matches
- // foo.txt/** doesn't match foo.txt
- if (!entries)
- return cb()
-
- // test without the globstar, and with every child both below
- // and replacing the globstar.
- var remainWithoutGlobStar = remain.slice(1);
- var gspref = prefix ? [ prefix ] : [];
- var noGlobStar = gspref.concat(remainWithoutGlobStar);
-
- // the noGlobStar pattern exits the inGlobStar state
- this._process(noGlobStar, index, false, cb);
-
- var isSym = this.symlinks[abs];
- var len = entries.length;
-
- // If it's a symlink, and we're in a globstar, then stop
- if (isSym && inGlobStar)
- return cb()
-
- for (var i = 0; i < len; i++) {
- var e = entries[i];
- if (e.charAt(0) === '.' && !this.dot)
- continue
-
- // these two cases enter the inGlobStar state
- var instead = gspref.concat(entries[i], remainWithoutGlobStar);
- this._process(instead, index, true, cb);
-
- var below = gspref.concat(entries[i], remain);
- this._process(below, index, true, cb);
- }
-
- cb();
-};
-
-Glob.prototype._processSimple = function (prefix, index, cb) {
- // XXX review this. Shouldn't it be doing the mounting etc
- // before doing stat? kinda weird?
- var self = this;
- this._stat(prefix, function (er, exists) {
- self._processSimple2(prefix, index, er, exists, cb);
- });
-};
-Glob.prototype._processSimple2 = function (prefix, index, er, exists, cb) {
-
- //console.error('ps2', prefix, exists)
-
- if (!this.matches[index])
- this.matches[index] = Object.create(null);
-
- // If it doesn't exist, then just mark the lack of results
- if (!exists)
- return cb()
-
- if (prefix && pathIsAbsolute(prefix) && !this.nomount) {
- var trail = /[\/\\]$/.test(prefix);
- if (prefix.charAt(0) === '/') {
- prefix = path__default['default'].join(this.root, prefix);
- } else {
- prefix = path__default['default'].resolve(this.root, prefix);
- if (trail)
- prefix += '/';
- }
- }
-
- if (process.platform === 'win32')
- prefix = prefix.replace(/\\/g, '/');
-
- // Mark this as a match
- this._emitMatch(index, prefix);
- cb();
-};
-
-// Returns either 'DIR', 'FILE', or false
-Glob.prototype._stat = function (f, cb) {
- var abs = this._makeAbs(f);
- var needDir = f.slice(-1) === '/';
-
- if (f.length > this.maxLength)
- return cb()
-
- if (!this.stat && ownProp$2(this.cache, abs)) {
- var c = this.cache[abs];
-
- if (Array.isArray(c))
- c = 'DIR';
-
- // It exists, but maybe not how we need it
- if (!needDir || c === 'DIR')
- return cb(null, c)
-
- if (needDir && c === 'FILE')
- return cb()
-
- // otherwise we have to stat, because maybe c=true
- // if we know it exists, but not what it is.
- }
- var stat = this.statCache[abs];
- if (stat !== undefined) {
- if (stat === false)
- return cb(null, stat)
- else {
- var type = stat.isDirectory() ? 'DIR' : 'FILE';
- if (needDir && type === 'FILE')
- return cb()
- else
- return cb(null, type, stat)
- }
- }
-
- var self = this;
- var statcb = inflight_1('stat\0' + abs, lstatcb_);
- if (statcb)
- fs__default['default'].lstat(abs, statcb);
-
- function lstatcb_ (er, lstat) {
- if (lstat && lstat.isSymbolicLink()) {
- // If it's a symlink, then treat it as the target, unless
- // the target does not exist, then treat it as a file.
- return fs__default['default'].stat(abs, function (er, stat) {
- if (er)
- self._stat2(f, abs, null, lstat, cb);
- else
- self._stat2(f, abs, er, stat, cb);
- })
- } else {
- self._stat2(f, abs, er, lstat, cb);
- }
- }
-};
-
-Glob.prototype._stat2 = function (f, abs, er, stat, cb) {
- if (er && (er.code === 'ENOENT' || er.code === 'ENOTDIR')) {
- this.statCache[abs] = false;
- return cb()
- }
-
- var needDir = f.slice(-1) === '/';
- this.statCache[abs] = stat;
-
- if (abs.slice(-1) === '/' && stat && !stat.isDirectory())
- return cb(null, false, stat)
-
- var c = true;
- if (stat)
- c = stat.isDirectory() ? 'DIR' : 'FILE';
- this.cache[abs] = this.cache[abs] || c;
-
- if (needDir && c === 'FILE')
- return cb()
-
- return cb(null, c, stat)
-};
-
-var glob$1 = glob_1;
-
-module.exports = glob$1;
diff --git a/tools/build/cbt/process.js b/tools/build/cbt/process.js
deleted file mode 100644
index ecd150b8d4..0000000000
--- a/tools/build/cbt/process.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * @file
- * @copyright 2020 Aleksej Komarov
- * @license MIT
- */
-
-const { spawn } = require('child_process');
-const { resolve: resolvePath } = require('path');
-const { stat } = require('./fs');
-
-/**
- * @type {import('child_process').ChildProcessWithoutNullStreams}
- */
-const children = new Set();
-
-const killChildren = () => {
- for (const child of children) {
- child.kill('SIGTERM');
- children.delete(child);
- console.log('killed child process');
- }
-};
-
-const trap = (signals, handler) => {
- let readline;
- if (process.platform === 'win32') {
- readline = require('readline').createInterface({
- input: process.stdin,
- output: process.stdout,
- });
- }
- for (const signal of signals) {
- const handleSignal = () => handler(signal);
- if (signal === 'EXIT') {
- process.on('exit', handleSignal);
- continue;
- }
- if (readline) {
- readline.on('SIG' + signal, handleSignal);
- }
- process.on('SIG' + signal, handleSignal);
- }
-};
-
-trap(['EXIT', 'BREAK', 'HUP', 'INT', 'TERM'], signal => {
- if (signal !== 'EXIT') {
- console.log('Received', signal);
- }
- killChildren();
- if (signal !== 'EXIT') {
- process.exit(1);
- }
-});
-
-const exceptionHandler = err => {
- console.log(err);
- killChildren();
- process.exit(1);
-};
-
-process.on('unhandledRejection', exceptionHandler);
-process.on('uncaughtException', exceptionHandler);
-
-class ExitError extends Error {}
-
-/**
- * @param {string} executable
- * @param {string[]} args
- * @param {import('child_process').SpawnOptionsWithoutStdio} options
- */
-const exec = (executable, args, options) => {
- return new Promise((resolve, reject) => {
- // If executable exists relative to the current directory,
- // use that executable, otherwise spawn should fall back to
- // running it from PATH.
- if (stat(executable)) {
- executable = resolvePath(executable);
- }
- const child = spawn(executable, args, options);
- children.add(child);
- child.stdout.pipe(process.stdout, { end: false });
- child.stderr.pipe(process.stderr, { end: false });
- child.stdin.end();
- child.on('error', err => reject(err));
- child.on('exit', code => {
- children.delete(child);
- if (code !== 0) {
- const error = new ExitError('Process exited with code: ' + code);
- error.code = code;
- reject(error);
- }
- else {
- resolve(code);
- }
- });
- });
-};
-
-module.exports = {
- exec,
- ExitError,
-};
diff --git a/tools/build/cbt/task.js b/tools/build/cbt/task.js
deleted file mode 100644
index f0782bfe1e..0000000000
--- a/tools/build/cbt/task.js
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * @file
- * @copyright 2020 Aleksej Komarov
- * @license MIT
- */
-
-const { compareFiles, Glob, File } = require('./fs');
-
-class Task {
- constructor(name) {
- this.name = name;
- this.sources = [];
- this.targets = [];
- this.script = null;
- }
-
- depends(path) {
- if (path.includes('*')) {
- this.sources.push(new Glob(path));
- }
- else {
- this.sources.push(new File(path));
- }
- return this;
- }
-
- provides(path) {
- if (path.includes('*')) {
- this.targets.push(new Glob(path));
- }
- else {
- this.targets.push(new File(path));
- }
- return this;
- }
-
- build(script) {
- this.script = script;
- return this;
- }
-
- async run() {
- /**
- * @returns {File[]}
- */
- const getFiles = files => files
- .flatMap(file => {
- if (file instanceof Glob) {
- return file.toFiles();
- }
- if (file instanceof File) {
- return file;
- }
- })
- .filter(Boolean);
- // Normalize all our dependencies by converting globs to files
- const fileSources = getFiles(this.sources);
- const fileTargets = getFiles(this.targets);
- // Consider dependencies first, and skip the task if it
- // doesn't need a rebuild.
- let needsRebuild = 'no targets';
- if (fileTargets.length > 0) {
- needsRebuild = compareFiles(fileSources, fileTargets);
- if (!needsRebuild) {
- console.warn(` => Skipping '${this.name}' (up to date)`);
- return;
- }
- }
- if (!this.script) {
- return;
- }
- if (process.env.DEBUG && needsRebuild) {
- console.debug(` Reason: ${needsRebuild}`);
- }
- console.warn(` => Starting '${this.name}'`);
- const startedAt = Date.now();
- // Run the script
- await this.script();
- // Touch all targets so that they don't rebuild again
- if (fileTargets.length > 0) {
- for (const file of fileTargets) {
- file.touch();
- }
- }
- const time = ((Date.now() - startedAt) / 1000) + 's';
- console.warn(` => Finished '${this.name}' in ${time}`);
- }
-}
-
-const runTasks = async tasks => {
- const startedAt = Date.now();
- // Run all if none of the tasks were specified in command line
- const runAll = !tasks.some(task => process.argv.includes(task.name));
- for (const task of tasks) {
- if (runAll || process.argv.includes(task.name)) {
- await task.run();
- }
- }
- const time = ((Date.now() - startedAt) / 1000) + 's';
- console.log(` => Done in ${time}`);
- process.exit();
-};
-
-module.exports = {
- Task,
- runTasks,
-};
diff --git a/tools/build/juke/index.d.ts b/tools/build/juke/index.d.ts
new file mode 100644
index 0000000000..cdc30ea577
--- /dev/null
+++ b/tools/build/juke/index.d.ts
@@ -0,0 +1,248 @@
+// Generated by dts-bundle-generator v5.9.0
+
+///
+
+import _chalk from 'chalk';
+import { SpawnOptionsWithoutStdio } from 'child_process';
+import EventEmitter from 'events';
+
+/**
+ * Change the current working directory of the Node.js process.
+ *
+ * Second argument is a file (or directory), relative to which chdir will be
+ * performed. This is usually `import.meta.url`.
+ */
+export declare const chdir: (directory: string, relativeTo?: string | undefined) => void;
+export declare const logger: {
+ log: (...args: unknown[]) => void;
+ error: (...args: unknown[]) => void;
+ action: (...args: unknown[]) => void;
+ warn: (...args: unknown[]) => void;
+ info: (...args: unknown[]) => void;
+ debug: (...args: unknown[]) => void;
+};
+export declare type ParameterType = (string | string[] | number | number[] | boolean | boolean[]);
+export declare type StringType = ("string" | "string[]" | "number" | "number[]" | "boolean" | "boolean[]");
+export declare type TypeByString = (T extends "string" ? string : T extends "string[]" ? string[] : T extends "number" ? number : T extends "number[]" ? number[] : T extends "boolean" ? boolean : T extends "boolean[]" ? boolean[] : never);
+export declare type ParameterConfig = {
+ /**
+ * Parameter name, as it would be used in CLI.
+ */
+ name?: string;
+ /**
+ * Parameter type, one of:
+ * - `string`
+ * - `string[]`
+ * - `number`
+ * - `number[]`
+ * - `boolean`
+ * - `boolean[]`
+ */
+ type: T;
+ /**
+ * Short flag for use in CLI, can only be a single character.
+ */
+ alias?: string;
+};
+export interface Parameter {
+ type: StringType;
+ name?: string;
+ alias?: string;
+ __internalType?: T;
+ isString(): this is Parameter;
+ isNumber(): this is Parameter;
+ isBoolean(): this is Parameter;
+ isArray(): this is Parameter;
+ toKebabCase(): string | undefined;
+ toConstCase(): string | undefined;
+ toCamelCase(): string | undefined;
+}
+export declare type ParameterCtor = {
+ new (config: ParameterConfig): Parameter>;
+};
+export declare const Parameter: ParameterCtor;
+export declare type ParameterCreator = (config: ParameterConfig) => Parameter>;
+export declare const createParameter: ParameterCreator;
+export declare type ExecutionContext = {
+ /** Get parameter value. */
+ get: (parameter: Parameter) => (T extends Array ? T : T | null);
+ args: string[];
+};
+export declare type BooleanLike = boolean | null | undefined;
+export declare type WithExecutionContext = (context: ExecutionContext) => R | Promise;
+export declare type WithOptionalExecutionContext = R | WithExecutionContext;
+export declare type DependsOn = WithOptionalExecutionContext<(Target | BooleanLike)[]>;
+export declare type ExecutesFn = WithExecutionContext;
+export declare type OnlyWhenFn = WithExecutionContext;
+export declare type FileIo = WithOptionalExecutionContext<(string | BooleanLike)[]>;
+export declare type TargetConfig = {
+ /**
+ * Target name. This parameter is required.
+ */
+ name?: string;
+ /**
+ * Dependencies for this target. They will be ran before executing this
+ * target, and may run in parallel.
+ */
+ dependsOn?: DependsOn;
+ /**
+ * Function that is delegated to the execution engine for building this
+ * target. It is normally an async function, which accepts a single
+ * argument - execution context (contains `get` for interacting with
+ * parameters).
+ *
+ * @example
+ * executes: async ({ get }) => {
+ * console.log(get(Parameter));
+ * },
+ */
+ executes?: ExecutesFn;
+ /**
+ * Files that are consumed by this target.
+ */
+ inputs?: FileIo;
+ /**
+ * Files that are produced by this target. Additionally, they are also
+ * touched every time target finishes executing in order to stop
+ * this target from re-running.
+ */
+ outputs?: FileIo;
+ /**
+ * Parameters that are local to this task. Can be retrieved via `get`
+ * in the executor function.
+ */
+ parameters?: Parameter[];
+ /**
+ * Target will run only when this function returns true. It accepts a
+ * single argument - execution context.
+ */
+ onlyWhen?: OnlyWhenFn;
+};
+export declare class Target {
+ name?: string;
+ dependsOn: DependsOn;
+ executes?: ExecutesFn;
+ inputs: FileIo;
+ outputs: FileIo;
+ parameters: Parameter[];
+ onlyWhen?: OnlyWhenFn;
+ constructor(target: TargetConfig);
+}
+export declare type TargetCreator = (target: TargetConfig) => Target;
+export declare const createTarget: TargetCreator;
+export declare type RunnerConfig = {
+ targets?: Target[];
+ default?: Target;
+ parameters?: Parameter[];
+ singleTarget?: boolean;
+};
+export declare const runner: {
+ config: RunnerConfig;
+ targets: Target[];
+ parameters: Parameter[];
+ workers: Worker[];
+ configure(config: RunnerConfig): void;
+ start(): Promise;
+};
+declare class Worker {
+ readonly target: Target;
+ readonly context: ExecutionContext;
+ readonly dependsOn: Target[];
+ dependencies: Set;
+ generator?: AsyncGenerator;
+ emitter: EventEmitter;
+ hasFailed: boolean;
+ constructor(target: Target, context: ExecutionContext, dependsOn: Target[]);
+ resolveDependency(target: Target): void;
+ rejectDependency(target: Target): void;
+ start(): void;
+ onFinish(fn: () => void): void;
+ onFail(fn: () => void): void;
+ private debugLog;
+ private process;
+}
+export declare class ExitCode extends Error {
+ code: number | null;
+ signal: string | null;
+ constructor(code: number | null, signal?: string | null);
+}
+export declare type ExecOptions = SpawnOptionsWithoutStdio & {
+ /**
+ * If `true`, this exec call will not pipe its output to stdio.
+ * @default false
+ */
+ silent?: boolean;
+ /**
+ * Throw an exception on non-zero exit code.
+ * @default true
+ */
+ throw?: boolean;
+};
+export declare type ExecReturn = {
+ /** Exit code of the program. */
+ code: number | null;
+ /** Signal received by the program which caused it to exit. */
+ signal: NodeJS.Signals | null;
+ /** Output collected from `stdout` */
+ stdout: string;
+ /** Output collected from `stderr` */
+ stderr: string;
+ /** A combined output collected from `stdout` and `stderr`. */
+ combined: string;
+};
+export declare const exec: (executable: string, args?: string[], options?: ExecOptions) => Promise;
+/**
+ * Unix style pathname pattern expansion.
+ *
+ * Perform a search matching a specified pattern according to the rules of
+ * the `glob` npm package. Path can be either absolute or relative, and can
+ * contain shell-style wildcards. Broken symlinks are included in the results
+ * (as in the shell). Whether or not the results are sorted depends on the
+ * file system.
+ *
+ * @returns A possibly empty list of file paths.
+ */
+export declare const glob: (globPath: string) => string[];
+export declare type RmOptions = {
+ /**
+ * If true, perform a recursive directory removal.
+ */
+ recursive?: boolean;
+ /**
+ * If true, exceptions will be ignored if file or directory does not exist.
+ */
+ force?: boolean;
+};
+/**
+ * Removes files and directories (synchronously). Supports globs.
+ */
+export declare const rm: (path: string, options?: RmOptions) => void;
+export declare const chalk: _chalk.Chalk & _chalk.ChalkFunction & {
+ supportsColor: false | _chalk.ColorSupport;
+ Level: _chalk.Level;
+ Color: ("black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan" | "white" | "gray" | "grey" | "blackBright" | "redBright" | "greenBright" | "yellowBright" | "blueBright" | "magentaBright" | "cyanBright" | "whiteBright") | ("bgBlack" | "bgRed" | "bgGreen" | "bgYellow" | "bgBlue" | "bgMagenta" | "bgCyan" | "bgWhite" | "bgGray" | "bgGrey" | "bgBlackBright" | "bgRedBright" | "bgGreenBright" | "bgYellowBright" | "bgBlueBright" | "bgMagentaBright" | "bgCyanBright" | "bgWhiteBright");
+ ForegroundColor: "black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan" | "white" | "gray" | "grey" | "blackBright" | "redBright" | "greenBright" | "yellowBright" | "blueBright" | "magentaBright" | "cyanBright" | "whiteBright";
+ BackgroundColor: "bgBlack" | "bgRed" | "bgGreen" | "bgYellow" | "bgBlue" | "bgMagenta" | "bgCyan" | "bgWhite" | "bgGray" | "bgGrey" | "bgBlackBright" | "bgRedBright" | "bgGreenBright" | "bgYellowBright" | "bgBlueBright" | "bgMagentaBright" | "bgCyanBright" | "bgWhiteBright";
+ Modifiers: "bold" | "reset" | "dim" | "italic" | "underline" | "inverse" | "hidden" | "strikethrough" | "visible";
+ stderr: _chalk.Chalk & {
+ supportsColor: false | _chalk.ColorSupport;
+ };
+};
+export declare type SetupConfig = {
+ file: string;
+ /**
+ * If true, CLI will only accept a single target to run and will receive all
+ * passed arguments as is (not only flags).
+ */
+ singleTarget?: boolean;
+};
+/**
+ * Configures Juke Build and starts executing targets.
+ *
+ * @param config Juke Build configuration.
+ * @returns Exit code of the whole runner process.
+ */
+export declare const setup: (config: SetupConfig) => Promise;
+export declare const sleep: (time: number) => Promise;
+
+export {};
diff --git a/tools/build/juke/index.js b/tools/build/juke/index.js
new file mode 100644
index 0000000000..4ee8fbf0bf
--- /dev/null
+++ b/tools/build/juke/index.js
@@ -0,0 +1,5128 @@
+var __create = Object.create;
+var __defProp = Object.defineProperty;
+var __defProps = Object.defineProperties;
+var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
+var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
+var __getOwnPropNames = Object.getOwnPropertyNames;
+var __getOwnPropSymbols = Object.getOwnPropertySymbols;
+var __getProtoOf = Object.getPrototypeOf;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __propIsEnum = Object.prototype.propertyIsEnumerable;
+var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
+var __spreadValues = (a, b) => {
+ for (var prop in b || (b = {}))
+ if (__hasOwnProp.call(b, prop))
+ __defNormalProp(a, prop, b[prop]);
+ if (__getOwnPropSymbols)
+ for (var prop of __getOwnPropSymbols(b)) {
+ if (__propIsEnum.call(b, prop))
+ __defNormalProp(a, prop, b[prop]);
+ }
+ return a;
+};
+var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
+var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
+var __objRest = (source, exclude) => {
+ var target = {};
+ for (var prop in source)
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
+ target[prop] = source[prop];
+ if (source != null && __getOwnPropSymbols)
+ for (var prop of __getOwnPropSymbols(source)) {
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
+ target[prop] = source[prop];
+ }
+ return target;
+};
+var __commonJS = (cb, mod) => function __require() {
+ return mod || (0, cb[Object.keys(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
+};
+var __export = (target, all) => {
+ __markAsModule(target);
+ for (var name in all)
+ __defProp(target, name, { get: all[name], enumerable: true });
+};
+var __reExport = (target, module2, desc) => {
+ if (module2 && typeof module2 === "object" || typeof module2 === "function") {
+ for (let key of __getOwnPropNames(module2))
+ if (!__hasOwnProp.call(target, key) && key !== "default")
+ __defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
+ }
+ return target;
+};
+var __toModule = (module2) => {
+ return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
+};
+
+// pnp:color-name-npm-1.1.4-025792b0ea-b044585952.zip/node_modules/color-name/index.js
+var require_color_name = __commonJS({
+ "pnp:color-name-npm-1.1.4-025792b0ea-b044585952.zip/node_modules/color-name/index.js"(exports, module2) {
+ "use strict";
+ module2.exports = {
+ "aliceblue": [240, 248, 255],
+ "antiquewhite": [250, 235, 215],
+ "aqua": [0, 255, 255],
+ "aquamarine": [127, 255, 212],
+ "azure": [240, 255, 255],
+ "beige": [245, 245, 220],
+ "bisque": [255, 228, 196],
+ "black": [0, 0, 0],
+ "blanchedalmond": [255, 235, 205],
+ "blue": [0, 0, 255],
+ "blueviolet": [138, 43, 226],
+ "brown": [165, 42, 42],
+ "burlywood": [222, 184, 135],
+ "cadetblue": [95, 158, 160],
+ "chartreuse": [127, 255, 0],
+ "chocolate": [210, 105, 30],
+ "coral": [255, 127, 80],
+ "cornflowerblue": [100, 149, 237],
+ "cornsilk": [255, 248, 220],
+ "crimson": [220, 20, 60],
+ "cyan": [0, 255, 255],
+ "darkblue": [0, 0, 139],
+ "darkcyan": [0, 139, 139],
+ "darkgoldenrod": [184, 134, 11],
+ "darkgray": [169, 169, 169],
+ "darkgreen": [0, 100, 0],
+ "darkgrey": [169, 169, 169],
+ "darkkhaki": [189, 183, 107],
+ "darkmagenta": [139, 0, 139],
+ "darkolivegreen": [85, 107, 47],
+ "darkorange": [255, 140, 0],
+ "darkorchid": [153, 50, 204],
+ "darkred": [139, 0, 0],
+ "darksalmon": [233, 150, 122],
+ "darkseagreen": [143, 188, 143],
+ "darkslateblue": [72, 61, 139],
+ "darkslategray": [47, 79, 79],
+ "darkslategrey": [47, 79, 79],
+ "darkturquoise": [0, 206, 209],
+ "darkviolet": [148, 0, 211],
+ "deeppink": [255, 20, 147],
+ "deepskyblue": [0, 191, 255],
+ "dimgray": [105, 105, 105],
+ "dimgrey": [105, 105, 105],
+ "dodgerblue": [30, 144, 255],
+ "firebrick": [178, 34, 34],
+ "floralwhite": [255, 250, 240],
+ "forestgreen": [34, 139, 34],
+ "fuchsia": [255, 0, 255],
+ "gainsboro": [220, 220, 220],
+ "ghostwhite": [248, 248, 255],
+ "gold": [255, 215, 0],
+ "goldenrod": [218, 165, 32],
+ "gray": [128, 128, 128],
+ "green": [0, 128, 0],
+ "greenyellow": [173, 255, 47],
+ "grey": [128, 128, 128],
+ "honeydew": [240, 255, 240],
+ "hotpink": [255, 105, 180],
+ "indianred": [205, 92, 92],
+ "indigo": [75, 0, 130],
+ "ivory": [255, 255, 240],
+ "khaki": [240, 230, 140],
+ "lavender": [230, 230, 250],
+ "lavenderblush": [255, 240, 245],
+ "lawngreen": [124, 252, 0],
+ "lemonchiffon": [255, 250, 205],
+ "lightblue": [173, 216, 230],
+ "lightcoral": [240, 128, 128],
+ "lightcyan": [224, 255, 255],
+ "lightgoldenrodyellow": [250, 250, 210],
+ "lightgray": [211, 211, 211],
+ "lightgreen": [144, 238, 144],
+ "lightgrey": [211, 211, 211],
+ "lightpink": [255, 182, 193],
+ "lightsalmon": [255, 160, 122],
+ "lightseagreen": [32, 178, 170],
+ "lightskyblue": [135, 206, 250],
+ "lightslategray": [119, 136, 153],
+ "lightslategrey": [119, 136, 153],
+ "lightsteelblue": [176, 196, 222],
+ "lightyellow": [255, 255, 224],
+ "lime": [0, 255, 0],
+ "limegreen": [50, 205, 50],
+ "linen": [250, 240, 230],
+ "magenta": [255, 0, 255],
+ "maroon": [128, 0, 0],
+ "mediumaquamarine": [102, 205, 170],
+ "mediumblue": [0, 0, 205],
+ "mediumorchid": [186, 85, 211],
+ "mediumpurple": [147, 112, 219],
+ "mediumseagreen": [60, 179, 113],
+ "mediumslateblue": [123, 104, 238],
+ "mediumspringgreen": [0, 250, 154],
+ "mediumturquoise": [72, 209, 204],
+ "mediumvioletred": [199, 21, 133],
+ "midnightblue": [25, 25, 112],
+ "mintcream": [245, 255, 250],
+ "mistyrose": [255, 228, 225],
+ "moccasin": [255, 228, 181],
+ "navajowhite": [255, 222, 173],
+ "navy": [0, 0, 128],
+ "oldlace": [253, 245, 230],
+ "olive": [128, 128, 0],
+ "olivedrab": [107, 142, 35],
+ "orange": [255, 165, 0],
+ "orangered": [255, 69, 0],
+ "orchid": [218, 112, 214],
+ "palegoldenrod": [238, 232, 170],
+ "palegreen": [152, 251, 152],
+ "paleturquoise": [175, 238, 238],
+ "palevioletred": [219, 112, 147],
+ "papayawhip": [255, 239, 213],
+ "peachpuff": [255, 218, 185],
+ "peru": [205, 133, 63],
+ "pink": [255, 192, 203],
+ "plum": [221, 160, 221],
+ "powderblue": [176, 224, 230],
+ "purple": [128, 0, 128],
+ "rebeccapurple": [102, 51, 153],
+ "red": [255, 0, 0],
+ "rosybrown": [188, 143, 143],
+ "royalblue": [65, 105, 225],
+ "saddlebrown": [139, 69, 19],
+ "salmon": [250, 128, 114],
+ "sandybrown": [244, 164, 96],
+ "seagreen": [46, 139, 87],
+ "seashell": [255, 245, 238],
+ "sienna": [160, 82, 45],
+ "silver": [192, 192, 192],
+ "skyblue": [135, 206, 235],
+ "slateblue": [106, 90, 205],
+ "slategray": [112, 128, 144],
+ "slategrey": [112, 128, 144],
+ "snow": [255, 250, 250],
+ "springgreen": [0, 255, 127],
+ "steelblue": [70, 130, 180],
+ "tan": [210, 180, 140],
+ "teal": [0, 128, 128],
+ "thistle": [216, 191, 216],
+ "tomato": [255, 99, 71],
+ "turquoise": [64, 224, 208],
+ "violet": [238, 130, 238],
+ "wheat": [245, 222, 179],
+ "white": [255, 255, 255],
+ "whitesmoke": [245, 245, 245],
+ "yellow": [255, 255, 0],
+ "yellowgreen": [154, 205, 50]
+ };
+ }
+});
+
+// pnp:color-convert-npm-2.0.1-79730e935b-79e6bdb9fd.zip/node_modules/color-convert/conversions.js
+var require_conversions = __commonJS({
+ "pnp:color-convert-npm-2.0.1-79730e935b-79e6bdb9fd.zip/node_modules/color-convert/conversions.js"(exports, module2) {
+ var cssKeywords = require_color_name();
+ var reverseKeywords = {};
+ for (const key of Object.keys(cssKeywords)) {
+ reverseKeywords[cssKeywords[key]] = key;
+ }
+ var convert = {
+ rgb: { channels: 3, labels: "rgb" },
+ hsl: { channels: 3, labels: "hsl" },
+ hsv: { channels: 3, labels: "hsv" },
+ hwb: { channels: 3, labels: "hwb" },
+ cmyk: { channels: 4, labels: "cmyk" },
+ xyz: { channels: 3, labels: "xyz" },
+ lab: { channels: 3, labels: "lab" },
+ lch: { channels: 3, labels: "lch" },
+ hex: { channels: 1, labels: ["hex"] },
+ keyword: { channels: 1, labels: ["keyword"] },
+ ansi16: { channels: 1, labels: ["ansi16"] },
+ ansi256: { channels: 1, labels: ["ansi256"] },
+ hcg: { channels: 3, labels: ["h", "c", "g"] },
+ apple: { channels: 3, labels: ["r16", "g16", "b16"] },
+ gray: { channels: 1, labels: ["gray"] }
+ };
+ module2.exports = convert;
+ for (const model of Object.keys(convert)) {
+ if (!("channels" in convert[model])) {
+ throw new Error("missing channels property: " + model);
+ }
+ if (!("labels" in convert[model])) {
+ throw new Error("missing channel labels property: " + model);
+ }
+ if (convert[model].labels.length !== convert[model].channels) {
+ throw new Error("channel and label counts mismatch: " + model);
+ }
+ const { channels, labels } = convert[model];
+ delete convert[model].channels;
+ delete convert[model].labels;
+ Object.defineProperty(convert[model], "channels", { value: channels });
+ Object.defineProperty(convert[model], "labels", { value: labels });
+ }
+ convert.rgb.hsl = function(rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const min = Math.min(r, g, b);
+ const max = Math.max(r, g, b);
+ const delta = max - min;
+ let h;
+ let s;
+ if (max === min) {
+ h = 0;
+ } else if (r === max) {
+ h = (g - b) / delta;
+ } else if (g === max) {
+ h = 2 + (b - r) / delta;
+ } else if (b === max) {
+ h = 4 + (r - g) / delta;
+ }
+ h = Math.min(h * 60, 360);
+ if (h < 0) {
+ h += 360;
+ }
+ const l = (min + max) / 2;
+ if (max === min) {
+ s = 0;
+ } else if (l <= 0.5) {
+ s = delta / (max + min);
+ } else {
+ s = delta / (2 - max - min);
+ }
+ return [h, s * 100, l * 100];
+ };
+ convert.rgb.hsv = function(rgb) {
+ let rdif;
+ let gdif;
+ let bdif;
+ let h;
+ let s;
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const v = Math.max(r, g, b);
+ const diff = v - Math.min(r, g, b);
+ const diffc = function(c) {
+ return (v - c) / 6 / diff + 1 / 2;
+ };
+ if (diff === 0) {
+ h = 0;
+ s = 0;
+ } else {
+ s = diff / v;
+ rdif = diffc(r);
+ gdif = diffc(g);
+ bdif = diffc(b);
+ if (r === v) {
+ h = bdif - gdif;
+ } else if (g === v) {
+ h = 1 / 3 + rdif - bdif;
+ } else if (b === v) {
+ h = 2 / 3 + gdif - rdif;
+ }
+ if (h < 0) {
+ h += 1;
+ } else if (h > 1) {
+ h -= 1;
+ }
+ }
+ return [
+ h * 360,
+ s * 100,
+ v * 100
+ ];
+ };
+ convert.rgb.hwb = function(rgb) {
+ const r = rgb[0];
+ const g = rgb[1];
+ let b = rgb[2];
+ const h = convert.rgb.hsl(rgb)[0];
+ const w = 1 / 255 * Math.min(r, Math.min(g, b));
+ b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
+ return [h, w * 100, b * 100];
+ };
+ convert.rgb.cmyk = function(rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const k = Math.min(1 - r, 1 - g, 1 - b);
+ const c = (1 - r - k) / (1 - k) || 0;
+ const m = (1 - g - k) / (1 - k) || 0;
+ const y = (1 - b - k) / (1 - k) || 0;
+ return [c * 100, m * 100, y * 100, k * 100];
+ };
+ function comparativeDistance(x, y) {
+ return (x[0] - y[0]) ** 2 + (x[1] - y[1]) ** 2 + (x[2] - y[2]) ** 2;
+ }
+ convert.rgb.keyword = function(rgb) {
+ const reversed = reverseKeywords[rgb];
+ if (reversed) {
+ return reversed;
+ }
+ let currentClosestDistance = Infinity;
+ let currentClosestKeyword;
+ for (const keyword of Object.keys(cssKeywords)) {
+ const value = cssKeywords[keyword];
+ const distance = comparativeDistance(rgb, value);
+ if (distance < currentClosestDistance) {
+ currentClosestDistance = distance;
+ currentClosestKeyword = keyword;
+ }
+ }
+ return currentClosestKeyword;
+ };
+ convert.keyword.rgb = function(keyword) {
+ return cssKeywords[keyword];
+ };
+ convert.rgb.xyz = function(rgb) {
+ let r = rgb[0] / 255;
+ let g = rgb[1] / 255;
+ let b = rgb[2] / 255;
+ r = r > 0.04045 ? ((r + 0.055) / 1.055) ** 2.4 : r / 12.92;
+ g = g > 0.04045 ? ((g + 0.055) / 1.055) ** 2.4 : g / 12.92;
+ b = b > 0.04045 ? ((b + 0.055) / 1.055) ** 2.4 : b / 12.92;
+ const x = r * 0.4124 + g * 0.3576 + b * 0.1805;
+ const y = r * 0.2126 + g * 0.7152 + b * 0.0722;
+ const z = r * 0.0193 + g * 0.1192 + b * 0.9505;
+ return [x * 100, y * 100, z * 100];
+ };
+ convert.rgb.lab = function(rgb) {
+ const xyz = convert.rgb.xyz(rgb);
+ let x = xyz[0];
+ let y = xyz[1];
+ let z = xyz[2];
+ x /= 95.047;
+ y /= 100;
+ z /= 108.883;
+ x = x > 8856e-6 ? x ** (1 / 3) : 7.787 * x + 16 / 116;
+ y = y > 8856e-6 ? y ** (1 / 3) : 7.787 * y + 16 / 116;
+ z = z > 8856e-6 ? z ** (1 / 3) : 7.787 * z + 16 / 116;
+ const l = 116 * y - 16;
+ const a = 500 * (x - y);
+ const b = 200 * (y - z);
+ return [l, a, b];
+ };
+ convert.hsl.rgb = function(hsl) {
+ const h = hsl[0] / 360;
+ const s = hsl[1] / 100;
+ const l = hsl[2] / 100;
+ let t2;
+ let t3;
+ let val;
+ if (s === 0) {
+ val = l * 255;
+ return [val, val, val];
+ }
+ if (l < 0.5) {
+ t2 = l * (1 + s);
+ } else {
+ t2 = l + s - l * s;
+ }
+ const t1 = 2 * l - t2;
+ const rgb = [0, 0, 0];
+ for (let i = 0; i < 3; i++) {
+ t3 = h + 1 / 3 * -(i - 1);
+ if (t3 < 0) {
+ t3++;
+ }
+ if (t3 > 1) {
+ t3--;
+ }
+ if (6 * t3 < 1) {
+ val = t1 + (t2 - t1) * 6 * t3;
+ } else if (2 * t3 < 1) {
+ val = t2;
+ } else if (3 * t3 < 2) {
+ val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
+ } else {
+ val = t1;
+ }
+ rgb[i] = val * 255;
+ }
+ return rgb;
+ };
+ convert.hsl.hsv = function(hsl) {
+ const h = hsl[0];
+ let s = hsl[1] / 100;
+ let l = hsl[2] / 100;
+ let smin = s;
+ const lmin = Math.max(l, 0.01);
+ l *= 2;
+ s *= l <= 1 ? l : 2 - l;
+ smin *= lmin <= 1 ? lmin : 2 - lmin;
+ const v = (l + s) / 2;
+ const sv = l === 0 ? 2 * smin / (lmin + smin) : 2 * s / (l + s);
+ return [h, sv * 100, v * 100];
+ };
+ convert.hsv.rgb = function(hsv) {
+ const h = hsv[0] / 60;
+ const s = hsv[1] / 100;
+ let v = hsv[2] / 100;
+ const hi = Math.floor(h) % 6;
+ const f = h - Math.floor(h);
+ const p = 255 * v * (1 - s);
+ const q = 255 * v * (1 - s * f);
+ const t = 255 * v * (1 - s * (1 - f));
+ v *= 255;
+ switch (hi) {
+ case 0:
+ return [v, t, p];
+ case 1:
+ return [q, v, p];
+ case 2:
+ return [p, v, t];
+ case 3:
+ return [p, q, v];
+ case 4:
+ return [t, p, v];
+ case 5:
+ return [v, p, q];
+ }
+ };
+ convert.hsv.hsl = function(hsv) {
+ const h = hsv[0];
+ const s = hsv[1] / 100;
+ const v = hsv[2] / 100;
+ const vmin = Math.max(v, 0.01);
+ let sl;
+ let l;
+ l = (2 - s) * v;
+ const lmin = (2 - s) * vmin;
+ sl = s * vmin;
+ sl /= lmin <= 1 ? lmin : 2 - lmin;
+ sl = sl || 0;
+ l /= 2;
+ return [h, sl * 100, l * 100];
+ };
+ convert.hwb.rgb = function(hwb) {
+ const h = hwb[0] / 360;
+ let wh = hwb[1] / 100;
+ let bl = hwb[2] / 100;
+ const ratio = wh + bl;
+ let f;
+ if (ratio > 1) {
+ wh /= ratio;
+ bl /= ratio;
+ }
+ const i = Math.floor(6 * h);
+ const v = 1 - bl;
+ f = 6 * h - i;
+ if ((i & 1) !== 0) {
+ f = 1 - f;
+ }
+ const n = wh + f * (v - wh);
+ let r;
+ let g;
+ let b;
+ switch (i) {
+ default:
+ case 6:
+ case 0:
+ r = v;
+ g = n;
+ b = wh;
+ break;
+ case 1:
+ r = n;
+ g = v;
+ b = wh;
+ break;
+ case 2:
+ r = wh;
+ g = v;
+ b = n;
+ break;
+ case 3:
+ r = wh;
+ g = n;
+ b = v;
+ break;
+ case 4:
+ r = n;
+ g = wh;
+ b = v;
+ break;
+ case 5:
+ r = v;
+ g = wh;
+ b = n;
+ break;
+ }
+ return [r * 255, g * 255, b * 255];
+ };
+ convert.cmyk.rgb = function(cmyk) {
+ const c = cmyk[0] / 100;
+ const m = cmyk[1] / 100;
+ const y = cmyk[2] / 100;
+ const k = cmyk[3] / 100;
+ const r = 1 - Math.min(1, c * (1 - k) + k);
+ const g = 1 - Math.min(1, m * (1 - k) + k);
+ const b = 1 - Math.min(1, y * (1 - k) + k);
+ return [r * 255, g * 255, b * 255];
+ };
+ convert.xyz.rgb = function(xyz) {
+ const x = xyz[0] / 100;
+ const y = xyz[1] / 100;
+ const z = xyz[2] / 100;
+ let r;
+ let g;
+ let b;
+ r = x * 3.2406 + y * -1.5372 + z * -0.4986;
+ g = x * -0.9689 + y * 1.8758 + z * 0.0415;
+ b = x * 0.0557 + y * -0.204 + z * 1.057;
+ r = r > 31308e-7 ? 1.055 * r ** (1 / 2.4) - 0.055 : r * 12.92;
+ g = g > 31308e-7 ? 1.055 * g ** (1 / 2.4) - 0.055 : g * 12.92;
+ b = b > 31308e-7 ? 1.055 * b ** (1 / 2.4) - 0.055 : b * 12.92;
+ r = Math.min(Math.max(0, r), 1);
+ g = Math.min(Math.max(0, g), 1);
+ b = Math.min(Math.max(0, b), 1);
+ return [r * 255, g * 255, b * 255];
+ };
+ convert.xyz.lab = function(xyz) {
+ let x = xyz[0];
+ let y = xyz[1];
+ let z = xyz[2];
+ x /= 95.047;
+ y /= 100;
+ z /= 108.883;
+ x = x > 8856e-6 ? x ** (1 / 3) : 7.787 * x + 16 / 116;
+ y = y > 8856e-6 ? y ** (1 / 3) : 7.787 * y + 16 / 116;
+ z = z > 8856e-6 ? z ** (1 / 3) : 7.787 * z + 16 / 116;
+ const l = 116 * y - 16;
+ const a = 500 * (x - y);
+ const b = 200 * (y - z);
+ return [l, a, b];
+ };
+ convert.lab.xyz = function(lab) {
+ const l = lab[0];
+ const a = lab[1];
+ const b = lab[2];
+ let x;
+ let y;
+ let z;
+ y = (l + 16) / 116;
+ x = a / 500 + y;
+ z = y - b / 200;
+ const y2 = y ** 3;
+ const x2 = x ** 3;
+ const z2 = z ** 3;
+ y = y2 > 8856e-6 ? y2 : (y - 16 / 116) / 7.787;
+ x = x2 > 8856e-6 ? x2 : (x - 16 / 116) / 7.787;
+ z = z2 > 8856e-6 ? z2 : (z - 16 / 116) / 7.787;
+ x *= 95.047;
+ y *= 100;
+ z *= 108.883;
+ return [x, y, z];
+ };
+ convert.lab.lch = function(lab) {
+ const l = lab[0];
+ const a = lab[1];
+ const b = lab[2];
+ let h;
+ const hr = Math.atan2(b, a);
+ h = hr * 360 / 2 / Math.PI;
+ if (h < 0) {
+ h += 360;
+ }
+ const c = Math.sqrt(a * a + b * b);
+ return [l, c, h];
+ };
+ convert.lch.lab = function(lch) {
+ const l = lch[0];
+ const c = lch[1];
+ const h = lch[2];
+ const hr = h / 360 * 2 * Math.PI;
+ const a = c * Math.cos(hr);
+ const b = c * Math.sin(hr);
+ return [l, a, b];
+ };
+ convert.rgb.ansi16 = function(args, saturation = null) {
+ const [r, g, b] = args;
+ let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation;
+ value = Math.round(value / 50);
+ if (value === 0) {
+ return 30;
+ }
+ let ansi = 30 + (Math.round(b / 255) << 2 | Math.round(g / 255) << 1 | Math.round(r / 255));
+ if (value === 2) {
+ ansi += 60;
+ }
+ return ansi;
+ };
+ convert.hsv.ansi16 = function(args) {
+ return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
+ };
+ convert.rgb.ansi256 = function(args) {
+ const r = args[0];
+ const g = args[1];
+ const b = args[2];
+ if (r === g && g === b) {
+ if (r < 8) {
+ return 16;
+ }
+ if (r > 248) {
+ return 231;
+ }
+ return Math.round((r - 8) / 247 * 24) + 232;
+ }
+ const ansi = 16 + 36 * Math.round(r / 255 * 5) + 6 * Math.round(g / 255 * 5) + Math.round(b / 255 * 5);
+ return ansi;
+ };
+ convert.ansi16.rgb = function(args) {
+ let color = args % 10;
+ if (color === 0 || color === 7) {
+ if (args > 50) {
+ color += 3.5;
+ }
+ color = color / 10.5 * 255;
+ return [color, color, color];
+ }
+ const mult = (~~(args > 50) + 1) * 0.5;
+ const r = (color & 1) * mult * 255;
+ const g = (color >> 1 & 1) * mult * 255;
+ const b = (color >> 2 & 1) * mult * 255;
+ return [r, g, b];
+ };
+ convert.ansi256.rgb = function(args) {
+ if (args >= 232) {
+ const c = (args - 232) * 10 + 8;
+ return [c, c, c];
+ }
+ args -= 16;
+ let rem;
+ const r = Math.floor(args / 36) / 5 * 255;
+ const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
+ const b = rem % 6 / 5 * 255;
+ return [r, g, b];
+ };
+ convert.rgb.hex = function(args) {
+ const integer = ((Math.round(args[0]) & 255) << 16) + ((Math.round(args[1]) & 255) << 8) + (Math.round(args[2]) & 255);
+ const string = integer.toString(16).toUpperCase();
+ return "000000".substring(string.length) + string;
+ };
+ convert.hex.rgb = function(args) {
+ const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
+ if (!match) {
+ return [0, 0, 0];
+ }
+ let colorString = match[0];
+ if (match[0].length === 3) {
+ colorString = colorString.split("").map((char) => {
+ return char + char;
+ }).join("");
+ }
+ const integer = parseInt(colorString, 16);
+ const r = integer >> 16 & 255;
+ const g = integer >> 8 & 255;
+ const b = integer & 255;
+ return [r, g, b];
+ };
+ convert.rgb.hcg = function(rgb) {
+ const r = rgb[0] / 255;
+ const g = rgb[1] / 255;
+ const b = rgb[2] / 255;
+ const max = Math.max(Math.max(r, g), b);
+ const min = Math.min(Math.min(r, g), b);
+ const chroma = max - min;
+ let grayscale;
+ let hue;
+ if (chroma < 1) {
+ grayscale = min / (1 - chroma);
+ } else {
+ grayscale = 0;
+ }
+ if (chroma <= 0) {
+ hue = 0;
+ } else if (max === r) {
+ hue = (g - b) / chroma % 6;
+ } else if (max === g) {
+ hue = 2 + (b - r) / chroma;
+ } else {
+ hue = 4 + (r - g) / chroma;
+ }
+ hue /= 6;
+ hue %= 1;
+ return [hue * 360, chroma * 100, grayscale * 100];
+ };
+ convert.hsl.hcg = function(hsl) {
+ const s = hsl[1] / 100;
+ const l = hsl[2] / 100;
+ const c = l < 0.5 ? 2 * s * l : 2 * s * (1 - l);
+ let f = 0;
+ if (c < 1) {
+ f = (l - 0.5 * c) / (1 - c);
+ }
+ return [hsl[0], c * 100, f * 100];
+ };
+ convert.hsv.hcg = function(hsv) {
+ const s = hsv[1] / 100;
+ const v = hsv[2] / 100;
+ const c = s * v;
+ let f = 0;
+ if (c < 1) {
+ f = (v - c) / (1 - c);
+ }
+ return [hsv[0], c * 100, f * 100];
+ };
+ convert.hcg.rgb = function(hcg) {
+ const h = hcg[0] / 360;
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+ if (c === 0) {
+ return [g * 255, g * 255, g * 255];
+ }
+ const pure = [0, 0, 0];
+ const hi = h % 1 * 6;
+ const v = hi % 1;
+ const w = 1 - v;
+ let mg = 0;
+ switch (Math.floor(hi)) {
+ case 0:
+ pure[0] = 1;
+ pure[1] = v;
+ pure[2] = 0;
+ break;
+ case 1:
+ pure[0] = w;
+ pure[1] = 1;
+ pure[2] = 0;
+ break;
+ case 2:
+ pure[0] = 0;
+ pure[1] = 1;
+ pure[2] = v;
+ break;
+ case 3:
+ pure[0] = 0;
+ pure[1] = w;
+ pure[2] = 1;
+ break;
+ case 4:
+ pure[0] = v;
+ pure[1] = 0;
+ pure[2] = 1;
+ break;
+ default:
+ pure[0] = 1;
+ pure[1] = 0;
+ pure[2] = w;
+ }
+ mg = (1 - c) * g;
+ return [
+ (c * pure[0] + mg) * 255,
+ (c * pure[1] + mg) * 255,
+ (c * pure[2] + mg) * 255
+ ];
+ };
+ convert.hcg.hsv = function(hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+ const v = c + g * (1 - c);
+ let f = 0;
+ if (v > 0) {
+ f = c / v;
+ }
+ return [hcg[0], f * 100, v * 100];
+ };
+ convert.hcg.hsl = function(hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+ const l = g * (1 - c) + 0.5 * c;
+ let s = 0;
+ if (l > 0 && l < 0.5) {
+ s = c / (2 * l);
+ } else if (l >= 0.5 && l < 1) {
+ s = c / (2 * (1 - l));
+ }
+ return [hcg[0], s * 100, l * 100];
+ };
+ convert.hcg.hwb = function(hcg) {
+ const c = hcg[1] / 100;
+ const g = hcg[2] / 100;
+ const v = c + g * (1 - c);
+ return [hcg[0], (v - c) * 100, (1 - v) * 100];
+ };
+ convert.hwb.hcg = function(hwb) {
+ const w = hwb[1] / 100;
+ const b = hwb[2] / 100;
+ const v = 1 - b;
+ const c = v - w;
+ let g = 0;
+ if (c < 1) {
+ g = (v - c) / (1 - c);
+ }
+ return [hwb[0], c * 100, g * 100];
+ };
+ convert.apple.rgb = function(apple) {
+ return [apple[0] / 65535 * 255, apple[1] / 65535 * 255, apple[2] / 65535 * 255];
+ };
+ convert.rgb.apple = function(rgb) {
+ return [rgb[0] / 255 * 65535, rgb[1] / 255 * 65535, rgb[2] / 255 * 65535];
+ };
+ convert.gray.rgb = function(args) {
+ return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
+ };
+ convert.gray.hsl = function(args) {
+ return [0, 0, args[0]];
+ };
+ convert.gray.hsv = convert.gray.hsl;
+ convert.gray.hwb = function(gray) {
+ return [0, 100, gray[0]];
+ };
+ convert.gray.cmyk = function(gray) {
+ return [0, 0, 0, gray[0]];
+ };
+ convert.gray.lab = function(gray) {
+ return [gray[0], 0, 0];
+ };
+ convert.gray.hex = function(gray) {
+ const val = Math.round(gray[0] / 100 * 255) & 255;
+ const integer = (val << 16) + (val << 8) + val;
+ const string = integer.toString(16).toUpperCase();
+ return "000000".substring(string.length) + string;
+ };
+ convert.rgb.gray = function(rgb) {
+ const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
+ return [val / 255 * 100];
+ };
+ }
+});
+
+// pnp:color-convert-npm-2.0.1-79730e935b-79e6bdb9fd.zip/node_modules/color-convert/route.js
+var require_route = __commonJS({
+ "pnp:color-convert-npm-2.0.1-79730e935b-79e6bdb9fd.zip/node_modules/color-convert/route.js"(exports, module2) {
+ var conversions = require_conversions();
+ function buildGraph() {
+ const graph = {};
+ const models = Object.keys(conversions);
+ for (let len = models.length, i = 0; i < len; i++) {
+ graph[models[i]] = {
+ distance: -1,
+ parent: null
+ };
+ }
+ return graph;
+ }
+ function deriveBFS(fromModel) {
+ const graph = buildGraph();
+ const queue = [fromModel];
+ graph[fromModel].distance = 0;
+ while (queue.length) {
+ const current = queue.pop();
+ const adjacents = Object.keys(conversions[current]);
+ for (let len = adjacents.length, i = 0; i < len; i++) {
+ const adjacent = adjacents[i];
+ const node = graph[adjacent];
+ if (node.distance === -1) {
+ node.distance = graph[current].distance + 1;
+ node.parent = current;
+ queue.unshift(adjacent);
+ }
+ }
+ }
+ return graph;
+ }
+ function link(from, to) {
+ return function(args) {
+ return to(from(args));
+ };
+ }
+ function wrapConversion(toModel, graph) {
+ const path2 = [graph[toModel].parent, toModel];
+ let fn = conversions[graph[toModel].parent][toModel];
+ let cur = graph[toModel].parent;
+ while (graph[cur].parent) {
+ path2.unshift(graph[cur].parent);
+ fn = link(conversions[graph[cur].parent][cur], fn);
+ cur = graph[cur].parent;
+ }
+ fn.conversion = path2;
+ return fn;
+ }
+ module2.exports = function(fromModel) {
+ const graph = deriveBFS(fromModel);
+ const conversion = {};
+ const models = Object.keys(graph);
+ for (let len = models.length, i = 0; i < len; i++) {
+ const toModel = models[i];
+ const node = graph[toModel];
+ if (node.parent === null) {
+ continue;
+ }
+ conversion[toModel] = wrapConversion(toModel, graph);
+ }
+ return conversion;
+ };
+ }
+});
+
+// pnp:color-convert-npm-2.0.1-79730e935b-79e6bdb9fd.zip/node_modules/color-convert/index.js
+var require_color_convert = __commonJS({
+ "pnp:color-convert-npm-2.0.1-79730e935b-79e6bdb9fd.zip/node_modules/color-convert/index.js"(exports, module2) {
+ var conversions = require_conversions();
+ var route = require_route();
+ var convert = {};
+ var models = Object.keys(conversions);
+ function wrapRaw(fn) {
+ const wrappedFn = function(...args) {
+ const arg0 = args[0];
+ if (arg0 === void 0 || arg0 === null) {
+ return arg0;
+ }
+ if (arg0.length > 1) {
+ args = arg0;
+ }
+ return fn(args);
+ };
+ if ("conversion" in fn) {
+ wrappedFn.conversion = fn.conversion;
+ }
+ return wrappedFn;
+ }
+ function wrapRounded(fn) {
+ const wrappedFn = function(...args) {
+ const arg0 = args[0];
+ if (arg0 === void 0 || arg0 === null) {
+ return arg0;
+ }
+ if (arg0.length > 1) {
+ args = arg0;
+ }
+ const result = fn(args);
+ if (typeof result === "object") {
+ for (let len = result.length, i = 0; i < len; i++) {
+ result[i] = Math.round(result[i]);
+ }
+ }
+ return result;
+ };
+ if ("conversion" in fn) {
+ wrappedFn.conversion = fn.conversion;
+ }
+ return wrappedFn;
+ }
+ models.forEach((fromModel) => {
+ convert[fromModel] = {};
+ Object.defineProperty(convert[fromModel], "channels", { value: conversions[fromModel].channels });
+ Object.defineProperty(convert[fromModel], "labels", { value: conversions[fromModel].labels });
+ const routes = route(fromModel);
+ const routeModels = Object.keys(routes);
+ routeModels.forEach((toModel) => {
+ const fn = routes[toModel];
+ convert[fromModel][toModel] = wrapRounded(fn);
+ convert[fromModel][toModel].raw = wrapRaw(fn);
+ });
+ });
+ module2.exports = convert;
+ }
+});
+
+// pnp:ansi-styles-npm-4.3.0-245c7d42c7-513b44c3b2.zip/node_modules/ansi-styles/index.js
+var require_ansi_styles = __commonJS({
+ "pnp:ansi-styles-npm-4.3.0-245c7d42c7-513b44c3b2.zip/node_modules/ansi-styles/index.js"(exports, module2) {
+ "use strict";
+ var wrapAnsi16 = (fn, offset) => (...args) => {
+ const code = fn(...args);
+ return `[${code + offset}m`;
+ };
+ var wrapAnsi256 = (fn, offset) => (...args) => {
+ const code = fn(...args);
+ return `[${38 + offset};5;${code}m`;
+ };
+ var wrapAnsi16m = (fn, offset) => (...args) => {
+ const rgb = fn(...args);
+ return `[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
+ };
+ var ansi2ansi = (n) => n;
+ var rgb2rgb = (r, g, b) => [r, g, b];
+ var setLazyProperty = (object, property, get) => {
+ Object.defineProperty(object, property, {
+ get: () => {
+ const value = get();
+ Object.defineProperty(object, property, {
+ value,
+ enumerable: true,
+ configurable: true
+ });
+ return value;
+ },
+ enumerable: true,
+ configurable: true
+ });
+ };
+ var colorConvert;
+ var makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
+ if (colorConvert === void 0) {
+ colorConvert = require_color_convert();
+ }
+ const offset = isBackground ? 10 : 0;
+ const styles = {};
+ for (const [sourceSpace, suite] of Object.entries(colorConvert)) {
+ const name = sourceSpace === "ansi16" ? "ansi" : sourceSpace;
+ if (sourceSpace === targetSpace) {
+ styles[name] = wrap(identity, offset);
+ } else if (typeof suite === "object") {
+ styles[name] = wrap(suite[targetSpace], offset);
+ }
+ }
+ return styles;
+ };
+ function assembleStyles() {
+ const codes = new Map();
+ const styles = {
+ modifier: {
+ reset: [0, 0],
+ bold: [1, 22],
+ dim: [2, 22],
+ italic: [3, 23],
+ underline: [4, 24],
+ inverse: [7, 27],
+ hidden: [8, 28],
+ strikethrough: [9, 29]
+ },
+ color: {
+ black: [30, 39],
+ red: [31, 39],
+ green: [32, 39],
+ yellow: [33, 39],
+ blue: [34, 39],
+ magenta: [35, 39],
+ cyan: [36, 39],
+ white: [37, 39],
+ blackBright: [90, 39],
+ redBright: [91, 39],
+ greenBright: [92, 39],
+ yellowBright: [93, 39],
+ blueBright: [94, 39],
+ magentaBright: [95, 39],
+ cyanBright: [96, 39],
+ whiteBright: [97, 39]
+ },
+ bgColor: {
+ bgBlack: [40, 49],
+ bgRed: [41, 49],
+ bgGreen: [42, 49],
+ bgYellow: [43, 49],
+ bgBlue: [44, 49],
+ bgMagenta: [45, 49],
+ bgCyan: [46, 49],
+ bgWhite: [47, 49],
+ bgBlackBright: [100, 49],
+ bgRedBright: [101, 49],
+ bgGreenBright: [102, 49],
+ bgYellowBright: [103, 49],
+ bgBlueBright: [104, 49],
+ bgMagentaBright: [105, 49],
+ bgCyanBright: [106, 49],
+ bgWhiteBright: [107, 49]
+ }
+ };
+ styles.color.gray = styles.color.blackBright;
+ styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
+ styles.color.grey = styles.color.blackBright;
+ styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
+ for (const [groupName, group] of Object.entries(styles)) {
+ for (const [styleName, style] of Object.entries(group)) {
+ styles[styleName] = {
+ open: `[${style[0]}m`,
+ close: `[${style[1]}m`
+ };
+ group[styleName] = styles[styleName];
+ codes.set(style[0], style[1]);
+ }
+ Object.defineProperty(styles, groupName, {
+ value: group,
+ enumerable: false
+ });
+ }
+ Object.defineProperty(styles, "codes", {
+ value: codes,
+ enumerable: false
+ });
+ styles.color.close = "[39m";
+ styles.bgColor.close = "[49m";
+ setLazyProperty(styles.color, "ansi", () => makeDynamicStyles(wrapAnsi16, "ansi16", ansi2ansi, false));
+ setLazyProperty(styles.color, "ansi256", () => makeDynamicStyles(wrapAnsi256, "ansi256", ansi2ansi, false));
+ setLazyProperty(styles.color, "ansi16m", () => makeDynamicStyles(wrapAnsi16m, "rgb", rgb2rgb, false));
+ setLazyProperty(styles.bgColor, "ansi", () => makeDynamicStyles(wrapAnsi16, "ansi16", ansi2ansi, true));
+ setLazyProperty(styles.bgColor, "ansi256", () => makeDynamicStyles(wrapAnsi256, "ansi256", ansi2ansi, true));
+ setLazyProperty(styles.bgColor, "ansi16m", () => makeDynamicStyles(wrapAnsi16m, "rgb", rgb2rgb, true));
+ return styles;
+ }
+ Object.defineProperty(module2, "exports", {
+ enumerable: true,
+ get: assembleStyles
+ });
+ }
+});
+
+// pnp:has-flag-npm-4.0.0-32af9f0536-261a135703.zip/node_modules/has-flag/index.js
+var require_has_flag = __commonJS({
+ "pnp:has-flag-npm-4.0.0-32af9f0536-261a135703.zip/node_modules/has-flag/index.js"(exports, module2) {
+ "use strict";
+ module2.exports = (flag, argv = process.argv) => {
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
+ const position = argv.indexOf(prefix + flag);
+ const terminatorPosition = argv.indexOf("--");
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
+ };
+ }
+});
+
+// pnp:supports-color-npm-7.2.0-606bfcf7da-3dda818de0.zip/node_modules/supports-color/index.js
+var require_supports_color = __commonJS({
+ "pnp:supports-color-npm-7.2.0-606bfcf7da-3dda818de0.zip/node_modules/supports-color/index.js"(exports, module2) {
+ "use strict";
+ var os = require("os");
+ var tty = require("tty");
+ var hasFlag = require_has_flag();
+ var { env } = process;
+ var forceColor;
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
+ forceColor = 0;
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
+ forceColor = 1;
+ }
+ if ("FORCE_COLOR" in env) {
+ if (env.FORCE_COLOR === "true") {
+ forceColor = 1;
+ } else if (env.FORCE_COLOR === "false") {
+ forceColor = 0;
+ } else {
+ forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
+ }
+ }
+ function translateLevel(level) {
+ if (level === 0) {
+ return false;
+ }
+ return {
+ level,
+ hasBasic: true,
+ has256: level >= 2,
+ has16m: level >= 3
+ };
+ }
+ function supportsColor(haveStream, streamIsTTY) {
+ if (forceColor === 0) {
+ return 0;
+ }
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
+ return 3;
+ }
+ if (hasFlag("color=256")) {
+ return 2;
+ }
+ if (haveStream && !streamIsTTY && forceColor === void 0) {
+ return 0;
+ }
+ const min = forceColor || 0;
+ if (env.TERM === "dumb") {
+ return min;
+ }
+ if (process.platform === "win32") {
+ const osRelease = os.release().split(".");
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
+ }
+ return 1;
+ }
+ if ("CI" in env) {
+ if (["TRAVIS", "CIRCLECI", "APPVEYOR", "GITLAB_CI", "GITHUB_ACTIONS", "BUILDKITE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
+ return 1;
+ }
+ return min;
+ }
+ if ("TEAMCITY_VERSION" in env) {
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
+ }
+ if (env.COLORTERM === "truecolor") {
+ return 3;
+ }
+ if ("TERM_PROGRAM" in env) {
+ const version2 = parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
+ switch (env.TERM_PROGRAM) {
+ case "iTerm.app":
+ return version2 >= 3 ? 3 : 2;
+ case "Apple_Terminal":
+ return 2;
+ }
+ }
+ if (/-256(color)?$/i.test(env.TERM)) {
+ return 2;
+ }
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
+ return 1;
+ }
+ if ("COLORTERM" in env) {
+ return 1;
+ }
+ return min;
+ }
+ function getSupportLevel(stream) {
+ const level = supportsColor(stream, stream && stream.isTTY);
+ return translateLevel(level);
+ }
+ module2.exports = {
+ supportsColor: getSupportLevel,
+ stdout: translateLevel(supportsColor(true, tty.isatty(1))),
+ stderr: translateLevel(supportsColor(true, tty.isatty(2)))
+ };
+ }
+});
+
+// pnp:chalk-npm-4.1.2-ba8b67ab80-fe75c9d5c7.zip/node_modules/chalk/source/util.js
+var require_util = __commonJS({
+ "pnp:chalk-npm-4.1.2-ba8b67ab80-fe75c9d5c7.zip/node_modules/chalk/source/util.js"(exports, module2) {
+ "use strict";
+ var stringReplaceAll = (string, substring, replacer) => {
+ let index = string.indexOf(substring);
+ if (index === -1) {
+ return string;
+ }
+ const substringLength = substring.length;
+ let endIndex = 0;
+ let returnValue = "";
+ do {
+ returnValue += string.substr(endIndex, index - endIndex) + substring + replacer;
+ endIndex = index + substringLength;
+ index = string.indexOf(substring, endIndex);
+ } while (index !== -1);
+ returnValue += string.substr(endIndex);
+ return returnValue;
+ };
+ var stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => {
+ let endIndex = 0;
+ let returnValue = "";
+ do {
+ const gotCR = string[index - 1] === "\r";
+ returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
+ endIndex = index + 1;
+ index = string.indexOf("\n", endIndex);
+ } while (index !== -1);
+ returnValue += string.substr(endIndex);
+ return returnValue;
+ };
+ module2.exports = {
+ stringReplaceAll,
+ stringEncaseCRLFWithFirstIndex
+ };
+ }
+});
+
+// pnp:chalk-npm-4.1.2-ba8b67ab80-fe75c9d5c7.zip/node_modules/chalk/source/templates.js
+var require_templates = __commonJS({
+ "pnp:chalk-npm-4.1.2-ba8b67ab80-fe75c9d5c7.zip/node_modules/chalk/source/templates.js"(exports, module2) {
+ "use strict";
+ var TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
+ var STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
+ var STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
+ var ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi;
+ var ESCAPES = new Map([
+ ["n", "\n"],
+ ["r", "\r"],
+ ["t", " "],
+ ["b", "\b"],
+ ["f", "\f"],
+ ["v", "\v"],
+ ["0", "\0"],
+ ["\\", "\\"],
+ ["e", ""],
+ ["a", "\x07"]
+ ]);
+ function unescape(c) {
+ const u = c[0] === "u";
+ const bracket = c[1] === "{";
+ if (u && !bracket && c.length === 5 || c[0] === "x" && c.length === 3) {
+ return String.fromCharCode(parseInt(c.slice(1), 16));
+ }
+ if (u && bracket) {
+ return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
+ }
+ return ESCAPES.get(c) || c;
+ }
+ function parseArguments(name, arguments_) {
+ const results = [];
+ const chunks = arguments_.trim().split(/\s*,\s*/g);
+ let matches;
+ for (const chunk of chunks) {
+ const number = Number(chunk);
+ if (!Number.isNaN(number)) {
+ results.push(number);
+ } else if (matches = chunk.match(STRING_REGEX)) {
+ results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character));
+ } else {
+ throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
+ }
+ }
+ return results;
+ }
+ function parseStyle(style) {
+ STYLE_REGEX.lastIndex = 0;
+ const results = [];
+ let matches;
+ while ((matches = STYLE_REGEX.exec(style)) !== null) {
+ const name = matches[1];
+ if (matches[2]) {
+ const args = parseArguments(name, matches[2]);
+ results.push([name].concat(args));
+ } else {
+ results.push([name]);
+ }
+ }
+ return results;
+ }
+ function buildStyle(chalk5, styles) {
+ const enabled = {};
+ for (const layer of styles) {
+ for (const style of layer.styles) {
+ enabled[style[0]] = layer.inverse ? null : style.slice(1);
+ }
+ }
+ let current = chalk5;
+ for (const [styleName, styles2] of Object.entries(enabled)) {
+ if (!Array.isArray(styles2)) {
+ continue;
+ }
+ if (!(styleName in current)) {
+ throw new Error(`Unknown Chalk style: ${styleName}`);
+ }
+ current = styles2.length > 0 ? current[styleName](...styles2) : current[styleName];
+ }
+ return current;
+ }
+ module2.exports = (chalk5, temporary) => {
+ const styles = [];
+ const chunks = [];
+ let chunk = [];
+ temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => {
+ if (escapeCharacter) {
+ chunk.push(unescape(escapeCharacter));
+ } else if (style) {
+ const string = chunk.join("");
+ chunk = [];
+ chunks.push(styles.length === 0 ? string : buildStyle(chalk5, styles)(string));
+ styles.push({ inverse, styles: parseStyle(style) });
+ } else if (close) {
+ if (styles.length === 0) {
+ throw new Error("Found extraneous } in Chalk template literal");
+ }
+ chunks.push(buildStyle(chalk5, styles)(chunk.join("")));
+ chunk = [];
+ styles.pop();
+ } else {
+ chunk.push(character);
+ }
+ });
+ chunks.push(chunk.join(""));
+ if (styles.length > 0) {
+ const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? "" : "s"} (\`}\`)`;
+ throw new Error(errMessage);
+ }
+ return chunks.join("");
+ };
+ }
+});
+
+// pnp:chalk-npm-4.1.2-ba8b67ab80-fe75c9d5c7.zip/node_modules/chalk/source/index.js
+var require_source = __commonJS({
+ "pnp:chalk-npm-4.1.2-ba8b67ab80-fe75c9d5c7.zip/node_modules/chalk/source/index.js"(exports, module2) {
+ "use strict";
+ var ansiStyles = require_ansi_styles();
+ var { stdout: stdoutColor, stderr: stderrColor } = require_supports_color();
+ var {
+ stringReplaceAll,
+ stringEncaseCRLFWithFirstIndex
+ } = require_util();
+ var { isArray } = Array;
+ var levelMapping = [
+ "ansi",
+ "ansi",
+ "ansi256",
+ "ansi16m"
+ ];
+ var styles = Object.create(null);
+ var applyOptions = (object, options = {}) => {
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
+ throw new Error("The `level` option should be an integer from 0 to 3");
+ }
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
+ object.level = options.level === void 0 ? colorLevel : options.level;
+ };
+ var ChalkClass = class {
+ constructor(options) {
+ return chalkFactory(options);
+ }
+ };
+ var chalkFactory = (options) => {
+ const chalk6 = {};
+ applyOptions(chalk6, options);
+ chalk6.template = (...arguments_) => chalkTag(chalk6.template, ...arguments_);
+ Object.setPrototypeOf(chalk6, Chalk.prototype);
+ Object.setPrototypeOf(chalk6.template, chalk6);
+ chalk6.template.constructor = () => {
+ throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.");
+ };
+ chalk6.template.Instance = ChalkClass;
+ return chalk6.template;
+ };
+ function Chalk(options) {
+ return chalkFactory(options);
+ }
+ for (const [styleName, style] of Object.entries(ansiStyles)) {
+ styles[styleName] = {
+ get() {
+ const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
+ Object.defineProperty(this, styleName, { value: builder });
+ return builder;
+ }
+ };
+ }
+ styles.visible = {
+ get() {
+ const builder = createBuilder(this, this._styler, true);
+ Object.defineProperty(this, "visible", { value: builder });
+ return builder;
+ }
+ };
+ var usedModels = ["rgb", "hex", "keyword", "hsl", "hsv", "hwb", "ansi", "ansi256"];
+ for (const model of usedModels) {
+ styles[model] = {
+ get() {
+ const { level } = this;
+ return function(...arguments_) {
+ const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
+ return createBuilder(this, styler, this._isEmpty);
+ };
+ }
+ };
+ }
+ for (const model of usedModels) {
+ const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
+ styles[bgModel] = {
+ get() {
+ const { level } = this;
+ return function(...arguments_) {
+ const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
+ return createBuilder(this, styler, this._isEmpty);
+ };
+ }
+ };
+ }
+ var proto = Object.defineProperties(() => {
+ }, __spreadProps(__spreadValues({}, styles), {
+ level: {
+ enumerable: true,
+ get() {
+ return this._generator.level;
+ },
+ set(level) {
+ this._generator.level = level;
+ }
+ }
+ }));
+ var createStyler = (open, close, parent) => {
+ let openAll;
+ let closeAll;
+ if (parent === void 0) {
+ openAll = open;
+ closeAll = close;
+ } else {
+ openAll = parent.openAll + open;
+ closeAll = close + parent.closeAll;
+ }
+ return {
+ open,
+ close,
+ openAll,
+ closeAll,
+ parent
+ };
+ };
+ var createBuilder = (self, _styler, _isEmpty) => {
+ const builder = (...arguments_) => {
+ if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) {
+ return applyStyle(builder, chalkTag(builder, ...arguments_));
+ }
+ return applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
+ };
+ Object.setPrototypeOf(builder, proto);
+ builder._generator = self;
+ builder._styler = _styler;
+ builder._isEmpty = _isEmpty;
+ return builder;
+ };
+ var applyStyle = (self, string) => {
+ if (self.level <= 0 || !string) {
+ return self._isEmpty ? "" : string;
+ }
+ let styler = self._styler;
+ if (styler === void 0) {
+ return string;
+ }
+ const { openAll, closeAll } = styler;
+ if (string.indexOf("") !== -1) {
+ while (styler !== void 0) {
+ string = stringReplaceAll(string, styler.close, styler.open);
+ styler = styler.parent;
+ }
+ }
+ const lfIndex = string.indexOf("\n");
+ if (lfIndex !== -1) {
+ string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
+ }
+ return openAll + string + closeAll;
+ };
+ var template;
+ var chalkTag = (chalk6, ...strings) => {
+ const [firstString] = strings;
+ if (!isArray(firstString) || !isArray(firstString.raw)) {
+ return strings.join(" ");
+ }
+ const arguments_ = strings.slice(1);
+ const parts = [firstString.raw[0]];
+ for (let i = 1; i < firstString.length; i++) {
+ parts.push(String(arguments_[i - 1]).replace(/[{}\\]/g, "\\$&"), String(firstString.raw[i]));
+ }
+ if (template === void 0) {
+ template = require_templates();
+ }
+ return template(chalk6, parts.join(""));
+ };
+ Object.defineProperties(Chalk.prototype, styles);
+ var chalk5 = Chalk();
+ chalk5.supportsColor = stdoutColor;
+ chalk5.stderr = Chalk({ level: stderrColor ? stderrColor.level : 0 });
+ chalk5.stderr.supportsColor = stderrColor;
+ module2.exports = chalk5;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/lowercase.js
+var require_lowercase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/lowercase.js"(exports, module2) {
+ "use strict";
+ function lowercase(str) {
+ str = String(str);
+ if (!str) {
+ return str;
+ }
+ return str.toLowerCase();
+ }
+ lowercase.isLowercase = function(str) {
+ return str && !/[A-Z]+/.test(str);
+ };
+ module2.exports = lowercase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/uppercase.js
+var require_uppercase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/uppercase.js"(exports, module2) {
+ "use strict";
+ function uppercase(str) {
+ str = String(str);
+ if (!str) {
+ return str;
+ }
+ return str.toUpperCase();
+ }
+ uppercase.isUppercase = function(str) {
+ return str && !/[a-z]+/.test(str);
+ };
+ module2.exports = uppercase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/camelcase.js
+var require_camelcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/camelcase.js"(exports, module2) {
+ "use strict";
+ var lowercase = require_lowercase();
+ var uppercase = require_uppercase();
+ var replacing = {
+ from: /[\-_:\.\s]([a-zA-Z])([a-zA-Z]*)/g,
+ to: function(match, $1, $2, offset, src) {
+ const len = $1.length;
+ return uppercase($1) + $2;
+ }
+ };
+ function camelcase2(str) {
+ if (camelcase2.isCamelcase(str)) {
+ return str;
+ }
+ str = String(str).replace(/^[\-_:\.\s]/, "");
+ if (!str) {
+ return str;
+ }
+ if (uppercase.isUppercase(str)) {
+ str = lowercase(str);
+ }
+ return lowercase(str[0]) + str.replace(replacing.from, replacing.to).slice(1).replace(/^([A-Z]+)([A-Z])/, (match, $1, $2) => lowercase($1) + $2);
+ }
+ camelcase2.isCamelcase = function(str) {
+ return str && /^[a-zA-Z]+$/.test(str) && lowercase(str[0]) === str[0];
+ };
+ module2.exports = camelcase2;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/capitalcase.js
+var require_capitalcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/capitalcase.js"(exports, module2) {
+ "use strict";
+ var uppercase = require_uppercase();
+ function capitalcase(str) {
+ str = String(str);
+ if (!str) {
+ return str;
+ }
+ return uppercase(str[0]) + str.slice(1);
+ }
+ module2.exports = capitalcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/snakecase.js
+var require_snakecase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/snakecase.js"(exports, module2) {
+ "use strict";
+ var lowercase = require_lowercase();
+ var uppercase = require_uppercase();
+ var JOINER = "_";
+ var replacing = {
+ from: /([A-Z]+)/g,
+ to(match, $1, offset, src) {
+ const prefix = offset === 0 ? "" : JOINER;
+ const len = $1.length;
+ if (len === 1) {
+ return prefix + lowercase($1);
+ }
+ const next = src.slice(offset + $1.length);
+ const isOneWord = uppercase.isUppercase($1) && next[0] === JOINER;
+ if (isOneWord) {
+ return prefix + lowercase($1);
+ }
+ const replaced = lowercase($1.substr(0, len - 1)) + JOINER + lowercase($1[len - 1]);
+ return prefix + replaced;
+ }
+ };
+ function snakecase(str) {
+ if (snakecase.isSnakecase(str)) {
+ return str;
+ }
+ str = String(str).replace(/[\-.:\s]/g, JOINER);
+ if (!str) {
+ return str;
+ }
+ if (uppercase.isUppercase(str)) {
+ str = lowercase(str);
+ }
+ return str.replace(replacing.from, replacing.to).replace(/_+/g, "_");
+ }
+ snakecase.isSnakecase = function(str) {
+ return str && /^[a-z_]+$/.test(str);
+ };
+ module2.exports = snakecase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/constcase.js
+var require_constcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/constcase.js"(exports, module2) {
+ "use strict";
+ var uppercase = require_uppercase();
+ var snakecase = require_snakecase();
+ function constcase2(str) {
+ if (constcase2.isConstcase(str)) {
+ return str;
+ }
+ return uppercase(snakecase(str));
+ }
+ constcase2.isConstcase = function(str) {
+ return str && /^[A-Z_]+$/.test(str);
+ };
+ module2.exports = constcase2;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/cramcase.js
+var require_cramcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/cramcase.js"(exports, module2) {
+ "use strict";
+ var snakecase = require_snakecase();
+ function cramcase(str) {
+ return snakecase(str).replace(/_/g, "");
+ }
+ module2.exports = cramcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/decapitalcase.js
+var require_decapitalcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/decapitalcase.js"(exports, module2) {
+ "use strict";
+ var lowercase = require_lowercase();
+ function capitalcase(str) {
+ str = String(str);
+ if (!str) {
+ return str;
+ }
+ return lowercase(str[0]) + str.slice(1);
+ }
+ module2.exports = capitalcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/dotcase.js
+var require_dotcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/dotcase.js"(exports, module2) {
+ "use strict";
+ var snakecase = require_snakecase();
+ function dotcase(str) {
+ return snakecase(str).replace(/_/g, ".");
+ }
+ module2.exports = dotcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/enumcase.js
+var require_enumcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/enumcase.js"(exports, module2) {
+ "use strict";
+ var snakecase = require_snakecase();
+ function enumcase(str) {
+ return snakecase(str).replace(/_/g, ":");
+ }
+ module2.exports = enumcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/pascalcase.js
+var require_pascalcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/pascalcase.js"(exports, module2) {
+ "use strict";
+ var camelcase2 = require_camelcase();
+ var capitalcase = require_capitalcase();
+ function pascalcase(str) {
+ return capitalcase(camelcase2(str));
+ }
+ module2.exports = pascalcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/pathcase.js
+var require_pathcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/pathcase.js"(exports, module2) {
+ "use strict";
+ var snakecase = require_snakecase();
+ function pathcase(str) {
+ return snakecase(str).replace(/_/g, "/");
+ }
+ module2.exports = pathcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/trimcase.js
+var require_trimcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/trimcase.js"(exports, module2) {
+ "use strict";
+ function trimcase(str) {
+ return String(str).trim();
+ }
+ module2.exports = trimcase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/sentencecase.js
+var require_sentencecase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/sentencecase.js"(exports, module2) {
+ "use strict";
+ var lowercase = require_lowercase();
+ var trimcase = require_trimcase();
+ var snakecase = require_snakecase();
+ var capitalcase = require_capitalcase();
+ var JOINER = " ";
+ function sentencecase(str) {
+ str = String(str).replace(/^[\-_\.\s]/g, JOINER);
+ if (!str) {
+ return str;
+ }
+ return capitalcase(snakecase(trimcase(str)).replace(/_/g, JOINER));
+ }
+ module2.exports = sentencecase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/spacecase.js
+var require_spacecase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/spacecase.js"(exports, module2) {
+ "use strict";
+ var snakecase = require_snakecase();
+ function spacecase(str) {
+ return snakecase(str).replace(/_/g, " ");
+ }
+ module2.exports = spacecase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/spinalcase.js
+var require_spinalcase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/spinalcase.js"(exports, module2) {
+ "use strict";
+ var snakecase = require_snakecase();
+ function spinalcase2(str) {
+ return snakecase(str).replace(/_/g, "-");
+ }
+ module2.exports = spinalcase2;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/titlecase.js
+var require_titlecase = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/titlecase.js"(exports, module2) {
+ "use strict";
+ var snakecase = require_snakecase();
+ var lowercase = require_lowercase();
+ var trimcase = require_trimcase();
+ var capitalcase = require_capitalcase();
+ var LOWERCASE_WORDS = "a,the,and,or,not,but,for,of".split(",");
+ function titlecase(str) {
+ return snakecase(str).split(/_/g).map(trimcase).map(function(word) {
+ var lower = !!~LOWERCASE_WORDS.indexOf(word);
+ if (lower) {
+ return lowercase(word);
+ } else {
+ return capitalcase(word);
+ }
+ }).join(" ");
+ }
+ module2.exports = titlecase;
+ }
+});
+
+// pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/index.js
+var require_lib = __commonJS({
+ "pnp:stringcase-npm-4.3.1-2f1c329337-741a448632.zip/node_modules/stringcase/lib/index.js"(exports, module2) {
+ "use strict";
+ var camelcase2 = require_camelcase();
+ var capitalcase = require_capitalcase();
+ var constcase2 = require_constcase();
+ var cramcase = require_cramcase();
+ var decapitalcase = require_decapitalcase();
+ var dotcase = require_dotcase();
+ var enumcase = require_enumcase();
+ var lowercase = require_lowercase();
+ var pascalcase = require_pascalcase();
+ var pathcase = require_pathcase();
+ var sentencecase = require_sentencecase();
+ var snakecase = require_snakecase();
+ var spacecase = require_spacecase();
+ var spinalcase2 = require_spinalcase();
+ var titlecase = require_titlecase();
+ var trimcase = require_trimcase();
+ var uppercase = require_uppercase();
+ exports.camelcase = camelcase2;
+ exports.capitalcase = capitalcase;
+ exports.constcase = constcase2;
+ exports.cramcase = cramcase;
+ exports.decapitalcase = decapitalcase;
+ exports.dotcase = dotcase;
+ exports.enumcase = enumcase;
+ exports.lowercase = lowercase;
+ exports.pascalcase = pascalcase;
+ exports.pathcase = pathcase;
+ exports.sentencecase = sentencecase;
+ exports.snakecase = snakecase;
+ exports.spacecase = spacecase;
+ exports.spinalcase = spinalcase2;
+ exports.titlecase = titlecase;
+ exports.trimcase = trimcase;
+ exports.uppercase = uppercase;
+ module2.exports = {
+ camelcase: camelcase2,
+ capitalcase,
+ constcase: constcase2,
+ cramcase,
+ decapitalcase,
+ dotcase,
+ enumcase,
+ lowercase,
+ pascalcase,
+ pathcase,
+ sentencecase,
+ snakecase,
+ spacecase,
+ spinalcase: spinalcase2,
+ titlecase,
+ trimcase,
+ uppercase
+ };
+ }
+});
+
+// pnp:fs.realpath-npm-1.0.0-c8f05d8126-99ddea01a7.zip/node_modules/fs.realpath/old.js
+var require_old = __commonJS({
+ "pnp:fs.realpath-npm-1.0.0-c8f05d8126-99ddea01a7.zip/node_modules/fs.realpath/old.js"(exports) {
+ var pathModule = require("path");
+ var isWindows = process.platform === "win32";
+ var fs4 = require("fs");
+ var DEBUG = process.env.NODE_DEBUG && /fs/.test(process.env.NODE_DEBUG);
+ function rethrow() {
+ var callback;
+ if (DEBUG) {
+ var backtrace = new Error();
+ callback = debugCallback;
+ } else
+ callback = missingCallback;
+ return callback;
+ function debugCallback(err) {
+ if (err) {
+ backtrace.message = err.message;
+ err = backtrace;
+ missingCallback(err);
+ }
+ }
+ function missingCallback(err) {
+ if (err) {
+ if (process.throwDeprecation)
+ throw err;
+ else if (!process.noDeprecation) {
+ var msg = "fs: missing callback " + (err.stack || err.message);
+ if (process.traceDeprecation)
+ console.trace(msg);
+ else
+ console.error(msg);
+ }
+ }
+ }
+ }
+ function maybeCallback(cb) {
+ return typeof cb === "function" ? cb : rethrow();
+ }
+ var normalize = pathModule.normalize;
+ if (isWindows) {
+ nextPartRe = /(.*?)(?:[\/\\]+|$)/g;
+ } else {
+ nextPartRe = /(.*?)(?:[\/]+|$)/g;
+ }
+ var nextPartRe;
+ if (isWindows) {
+ splitRootRe = /^(?:[a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?[\\\/]*/;
+ } else {
+ splitRootRe = /^[\/]*/;
+ }
+ var splitRootRe;
+ exports.realpathSync = function realpathSync(p, cache) {
+ p = pathModule.resolve(p);
+ if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
+ return cache[p];
+ }
+ var original = p, seenLinks = {}, knownHard = {};
+ var pos;
+ var current;
+ var base;
+ var previous;
+ start();
+ function start() {
+ var m = splitRootRe.exec(p);
+ pos = m[0].length;
+ current = m[0];
+ base = m[0];
+ previous = "";
+ if (isWindows && !knownHard[base]) {
+ fs4.lstatSync(base);
+ knownHard[base] = true;
+ }
+ }
+ while (pos < p.length) {
+ nextPartRe.lastIndex = pos;
+ var result = nextPartRe.exec(p);
+ previous = current;
+ current += result[0];
+ base = previous + result[1];
+ pos = nextPartRe.lastIndex;
+ if (knownHard[base] || cache && cache[base] === base) {
+ continue;
+ }
+ var resolvedLink;
+ if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
+ resolvedLink = cache[base];
+ } else {
+ var stat = fs4.lstatSync(base);
+ if (!stat.isSymbolicLink()) {
+ knownHard[base] = true;
+ if (cache)
+ cache[base] = base;
+ continue;
+ }
+ var linkTarget = null;
+ if (!isWindows) {
+ var id = stat.dev.toString(32) + ":" + stat.ino.toString(32);
+ if (seenLinks.hasOwnProperty(id)) {
+ linkTarget = seenLinks[id];
+ }
+ }
+ if (linkTarget === null) {
+ fs4.statSync(base);
+ linkTarget = fs4.readlinkSync(base);
+ }
+ resolvedLink = pathModule.resolve(previous, linkTarget);
+ if (cache)
+ cache[base] = resolvedLink;
+ if (!isWindows)
+ seenLinks[id] = linkTarget;
+ }
+ p = pathModule.resolve(resolvedLink, p.slice(pos));
+ start();
+ }
+ if (cache)
+ cache[original] = p;
+ return p;
+ };
+ exports.realpath = function realpath(p, cache, cb) {
+ if (typeof cb !== "function") {
+ cb = maybeCallback(cache);
+ cache = null;
+ }
+ p = pathModule.resolve(p);
+ if (cache && Object.prototype.hasOwnProperty.call(cache, p)) {
+ return process.nextTick(cb.bind(null, null, cache[p]));
+ }
+ var original = p, seenLinks = {}, knownHard = {};
+ var pos;
+ var current;
+ var base;
+ var previous;
+ start();
+ function start() {
+ var m = splitRootRe.exec(p);
+ pos = m[0].length;
+ current = m[0];
+ base = m[0];
+ previous = "";
+ if (isWindows && !knownHard[base]) {
+ fs4.lstat(base, function(err) {
+ if (err)
+ return cb(err);
+ knownHard[base] = true;
+ LOOP();
+ });
+ } else {
+ process.nextTick(LOOP);
+ }
+ }
+ function LOOP() {
+ if (pos >= p.length) {
+ if (cache)
+ cache[original] = p;
+ return cb(null, p);
+ }
+ nextPartRe.lastIndex = pos;
+ var result = nextPartRe.exec(p);
+ previous = current;
+ current += result[0];
+ base = previous + result[1];
+ pos = nextPartRe.lastIndex;
+ if (knownHard[base] || cache && cache[base] === base) {
+ return process.nextTick(LOOP);
+ }
+ if (cache && Object.prototype.hasOwnProperty.call(cache, base)) {
+ return gotResolvedLink(cache[base]);
+ }
+ return fs4.lstat(base, gotStat);
+ }
+ function gotStat(err, stat) {
+ if (err)
+ return cb(err);
+ if (!stat.isSymbolicLink()) {
+ knownHard[base] = true;
+ if (cache)
+ cache[base] = base;
+ return process.nextTick(LOOP);
+ }
+ if (!isWindows) {
+ var id = stat.dev.toString(32) + ":" + stat.ino.toString(32);
+ if (seenLinks.hasOwnProperty(id)) {
+ return gotTarget(null, seenLinks[id], base);
+ }
+ }
+ fs4.stat(base, function(err2) {
+ if (err2)
+ return cb(err2);
+ fs4.readlink(base, function(err3, target) {
+ if (!isWindows)
+ seenLinks[id] = target;
+ gotTarget(err3, target);
+ });
+ });
+ }
+ function gotTarget(err, target, base2) {
+ if (err)
+ return cb(err);
+ var resolvedLink = pathModule.resolve(previous, target);
+ if (cache)
+ cache[base2] = resolvedLink;
+ gotResolvedLink(resolvedLink);
+ }
+ function gotResolvedLink(resolvedLink) {
+ p = pathModule.resolve(resolvedLink, p.slice(pos));
+ start();
+ }
+ };
+ }
+});
+
+// pnp:fs.realpath-npm-1.0.0-c8f05d8126-99ddea01a7.zip/node_modules/fs.realpath/index.js
+var require_fs = __commonJS({
+ "pnp:fs.realpath-npm-1.0.0-c8f05d8126-99ddea01a7.zip/node_modules/fs.realpath/index.js"(exports, module2) {
+ module2.exports = realpath;
+ realpath.realpath = realpath;
+ realpath.sync = realpathSync;
+ realpath.realpathSync = realpathSync;
+ realpath.monkeypatch = monkeypatch;
+ realpath.unmonkeypatch = unmonkeypatch;
+ var fs4 = require("fs");
+ var origRealpath = fs4.realpath;
+ var origRealpathSync = fs4.realpathSync;
+ var version2 = process.version;
+ var ok = /^v[0-5]\./.test(version2);
+ var old = require_old();
+ function newError(er) {
+ return er && er.syscall === "realpath" && (er.code === "ELOOP" || er.code === "ENOMEM" || er.code === "ENAMETOOLONG");
+ }
+ function realpath(p, cache, cb) {
+ if (ok) {
+ return origRealpath(p, cache, cb);
+ }
+ if (typeof cache === "function") {
+ cb = cache;
+ cache = null;
+ }
+ origRealpath(p, cache, function(er, result) {
+ if (newError(er)) {
+ old.realpath(p, cache, cb);
+ } else {
+ cb(er, result);
+ }
+ });
+ }
+ function realpathSync(p, cache) {
+ if (ok) {
+ return origRealpathSync(p, cache);
+ }
+ try {
+ return origRealpathSync(p, cache);
+ } catch (er) {
+ if (newError(er)) {
+ return old.realpathSync(p, cache);
+ } else {
+ throw er;
+ }
+ }
+ }
+ function monkeypatch() {
+ fs4.realpath = realpath;
+ fs4.realpathSync = realpathSync;
+ }
+ function unmonkeypatch() {
+ fs4.realpath = origRealpath;
+ fs4.realpathSync = origRealpathSync;
+ }
+ }
+});
+
+// pnp:concat-map-npm-0.0.1-85a921b7ee-902a9f5d89.zip/node_modules/concat-map/index.js
+var require_concat_map = __commonJS({
+ "pnp:concat-map-npm-0.0.1-85a921b7ee-902a9f5d89.zip/node_modules/concat-map/index.js"(exports, module2) {
+ module2.exports = function(xs, fn) {
+ var res = [];
+ for (var i = 0; i < xs.length; i++) {
+ var x = fn(xs[i], i);
+ if (isArray(x))
+ res.push.apply(res, x);
+ else
+ res.push(x);
+ }
+ return res;
+ };
+ var isArray = Array.isArray || function(xs) {
+ return Object.prototype.toString.call(xs) === "[object Array]";
+ };
+ }
+});
+
+// pnp:balanced-match-npm-1.0.0-951a2ad706-9b67bfe558.zip/node_modules/balanced-match/index.js
+var require_balanced_match = __commonJS({
+ "pnp:balanced-match-npm-1.0.0-951a2ad706-9b67bfe558.zip/node_modules/balanced-match/index.js"(exports, module2) {
+ "use strict";
+ module2.exports = balanced;
+ function balanced(a, b, str) {
+ if (a instanceof RegExp)
+ a = maybeMatch(a, str);
+ if (b instanceof RegExp)
+ b = maybeMatch(b, str);
+ var r = range(a, b, str);
+ return r && {
+ start: r[0],
+ end: r[1],
+ pre: str.slice(0, r[0]),
+ body: str.slice(r[0] + a.length, r[1]),
+ post: str.slice(r[1] + b.length)
+ };
+ }
+ function maybeMatch(reg, str) {
+ var m = str.match(reg);
+ return m ? m[0] : null;
+ }
+ balanced.range = range;
+ function range(a, b, str) {
+ var begs, beg, left, right, result;
+ var ai = str.indexOf(a);
+ var bi = str.indexOf(b, ai + 1);
+ var i = ai;
+ if (ai >= 0 && bi > 0) {
+ begs = [];
+ left = str.length;
+ while (i >= 0 && !result) {
+ if (i == ai) {
+ begs.push(i);
+ ai = str.indexOf(a, i + 1);
+ } else if (begs.length == 1) {
+ result = [begs.pop(), bi];
+ } else {
+ beg = begs.pop();
+ if (beg < left) {
+ left = beg;
+ right = bi;
+ }
+ bi = str.indexOf(b, i + 1);
+ }
+ i = ai < bi && ai >= 0 ? ai : bi;
+ }
+ if (begs.length) {
+ result = [left, right];
+ }
+ }
+ return result;
+ }
+ }
+});
+
+// pnp:brace-expansion-npm-1.1.11-fb95eb05ad-faf34a7bb0.zip/node_modules/brace-expansion/index.js
+var require_brace_expansion = __commonJS({
+ "pnp:brace-expansion-npm-1.1.11-fb95eb05ad-faf34a7bb0.zip/node_modules/brace-expansion/index.js"(exports, module2) {
+ var concatMap = require_concat_map();
+ var balanced = require_balanced_match();
+ module2.exports = expandTop;
+ var escSlash = "\0SLASH" + Math.random() + "\0";
+ var escOpen = "\0OPEN" + Math.random() + "\0";
+ var escClose = "\0CLOSE" + Math.random() + "\0";
+ var escComma = "\0COMMA" + Math.random() + "\0";
+ var escPeriod = "\0PERIOD" + Math.random() + "\0";
+ function numeric(str) {
+ return parseInt(str, 10) == str ? parseInt(str, 10) : str.charCodeAt(0);
+ }
+ function escapeBraces(str) {
+ return str.split("\\\\").join(escSlash).split("\\{").join(escOpen).split("\\}").join(escClose).split("\\,").join(escComma).split("\\.").join(escPeriod);
+ }
+ function unescapeBraces(str) {
+ return str.split(escSlash).join("\\").split(escOpen).join("{").split(escClose).join("}").split(escComma).join(",").split(escPeriod).join(".");
+ }
+ function parseCommaParts(str) {
+ if (!str)
+ return [""];
+ var parts = [];
+ var m = balanced("{", "}", str);
+ if (!m)
+ return str.split(",");
+ var pre = m.pre;
+ var body = m.body;
+ var post = m.post;
+ var p = pre.split(",");
+ p[p.length - 1] += "{" + body + "}";
+ var postParts = parseCommaParts(post);
+ if (post.length) {
+ p[p.length - 1] += postParts.shift();
+ p.push.apply(p, postParts);
+ }
+ parts.push.apply(parts, p);
+ return parts;
+ }
+ function expandTop(str) {
+ if (!str)
+ return [];
+ if (str.substr(0, 2) === "{}") {
+ str = "\\{\\}" + str.substr(2);
+ }
+ return expand(escapeBraces(str), true).map(unescapeBraces);
+ }
+ function embrace(str) {
+ return "{" + str + "}";
+ }
+ function isPadded(el) {
+ return /^-?0\d/.test(el);
+ }
+ function lte(i, y) {
+ return i <= y;
+ }
+ function gte(i, y) {
+ return i >= y;
+ }
+ function expand(str, isTop) {
+ var expansions = [];
+ var m = balanced("{", "}", str);
+ if (!m || /\$$/.test(m.pre))
+ return [str];
+ var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
+ var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
+ var isSequence = isNumericSequence || isAlphaSequence;
+ var isOptions = m.body.indexOf(",") >= 0;
+ if (!isSequence && !isOptions) {
+ if (m.post.match(/,.*\}/)) {
+ str = m.pre + "{" + m.body + escClose + m.post;
+ return expand(str);
+ }
+ return [str];
+ }
+ var n;
+ if (isSequence) {
+ n = m.body.split(/\.\./);
+ } else {
+ n = parseCommaParts(m.body);
+ if (n.length === 1) {
+ n = expand(n[0], false).map(embrace);
+ if (n.length === 1) {
+ var post = m.post.length ? expand(m.post, false) : [""];
+ return post.map(function(p) {
+ return m.pre + n[0] + p;
+ });
+ }
+ }
+ }
+ var pre = m.pre;
+ var post = m.post.length ? expand(m.post, false) : [""];
+ var N;
+ if (isSequence) {
+ var x = numeric(n[0]);
+ var y = numeric(n[1]);
+ var width = Math.max(n[0].length, n[1].length);
+ var incr = n.length == 3 ? Math.abs(numeric(n[2])) : 1;
+ var test = lte;
+ var reverse = y < x;
+ if (reverse) {
+ incr *= -1;
+ test = gte;
+ }
+ var pad = n.some(isPadded);
+ N = [];
+ for (var i = x; test(i, y); i += incr) {
+ var c;
+ if (isAlphaSequence) {
+ c = String.fromCharCode(i);
+ if (c === "\\")
+ c = "";
+ } else {
+ c = String(i);
+ if (pad) {
+ var need = width - c.length;
+ if (need > 0) {
+ var z = new Array(need + 1).join("0");
+ if (i < 0)
+ c = "-" + z + c.slice(1);
+ else
+ c = z + c;
+ }
+ }
+ }
+ N.push(c);
+ }
+ } else {
+ N = concatMap(n, function(el) {
+ return expand(el, false);
+ });
+ }
+ for (var j = 0; j < N.length; j++) {
+ for (var k = 0; k < post.length; k++) {
+ var expansion = pre + N[j] + post[k];
+ if (!isTop || isSequence || expansion)
+ expansions.push(expansion);
+ }
+ }
+ return expansions;
+ }
+ }
+});
+
+// pnp:minimatch-npm-3.0.4-6e76f51c23-66ac295f8a.zip/node_modules/minimatch/minimatch.js
+var require_minimatch = __commonJS({
+ "pnp:minimatch-npm-3.0.4-6e76f51c23-66ac295f8a.zip/node_modules/minimatch/minimatch.js"(exports, module2) {
+ module2.exports = minimatch;
+ minimatch.Minimatch = Minimatch;
+ var path2 = { sep: "/" };
+ try {
+ path2 = require("path");
+ } catch (er) {
+ }
+ var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {};
+ var expand = require_brace_expansion();
+ var plTypes = {
+ "!": { open: "(?:(?!(?:", close: "))[^/]*?)" },
+ "?": { open: "(?:", close: ")?" },
+ "+": { open: "(?:", close: ")+" },
+ "*": { open: "(?:", close: ")*" },
+ "@": { open: "(?:", close: ")" }
+ };
+ var qmark = "[^/]";
+ var star = qmark + "*?";
+ var twoStarDot = "(?:(?!(?:\\/|^)(?:\\.{1,2})($|\\/)).)*?";
+ var twoStarNoDot = "(?:(?!(?:\\/|^)\\.).)*?";
+ var reSpecials = charSet("().*{}+?[]^$\\!");
+ function charSet(s) {
+ return s.split("").reduce(function(set, c) {
+ set[c] = true;
+ return set;
+ }, {});
+ }
+ var slashSplit = /\/+/;
+ minimatch.filter = filter;
+ function filter(pattern, options) {
+ options = options || {};
+ return function(p, i, list) {
+ return minimatch(p, pattern, options);
+ };
+ }
+ function ext(a, b) {
+ a = a || {};
+ b = b || {};
+ var t = {};
+ Object.keys(b).forEach(function(k) {
+ t[k] = b[k];
+ });
+ Object.keys(a).forEach(function(k) {
+ t[k] = a[k];
+ });
+ return t;
+ }
+ minimatch.defaults = function(def) {
+ if (!def || !Object.keys(def).length)
+ return minimatch;
+ var orig = minimatch;
+ var m = function minimatch2(p, pattern, options) {
+ return orig.minimatch(p, pattern, ext(def, options));
+ };
+ m.Minimatch = function Minimatch2(pattern, options) {
+ return new orig.Minimatch(pattern, ext(def, options));
+ };
+ return m;
+ };
+ Minimatch.defaults = function(def) {
+ if (!def || !Object.keys(def).length)
+ return Minimatch;
+ return minimatch.defaults(def).Minimatch;
+ };
+ function minimatch(p, pattern, options) {
+ if (typeof pattern !== "string") {
+ throw new TypeError("glob pattern string required");
+ }
+ if (!options)
+ options = {};
+ if (!options.nocomment && pattern.charAt(0) === "#") {
+ return false;
+ }
+ if (pattern.trim() === "")
+ return p === "";
+ return new Minimatch(pattern, options).match(p);
+ }
+ function Minimatch(pattern, options) {
+ if (!(this instanceof Minimatch)) {
+ return new Minimatch(pattern, options);
+ }
+ if (typeof pattern !== "string") {
+ throw new TypeError("glob pattern string required");
+ }
+ if (!options)
+ options = {};
+ pattern = pattern.trim();
+ if (path2.sep !== "/") {
+ pattern = pattern.split(path2.sep).join("/");
+ }
+ this.options = options;
+ this.set = [];
+ this.pattern = pattern;
+ this.regexp = null;
+ this.negate = false;
+ this.comment = false;
+ this.empty = false;
+ this.make();
+ }
+ Minimatch.prototype.debug = function() {
+ };
+ Minimatch.prototype.make = make;
+ function make() {
+ if (this._made)
+ return;
+ var pattern = this.pattern;
+ var options = this.options;
+ if (!options.nocomment && pattern.charAt(0) === "#") {
+ this.comment = true;
+ return;
+ }
+ if (!pattern) {
+ this.empty = true;
+ return;
+ }
+ this.parseNegate();
+ var set = this.globSet = this.braceExpand();
+ if (options.debug)
+ this.debug = console.error;
+ this.debug(this.pattern, set);
+ set = this.globParts = set.map(function(s) {
+ return s.split(slashSplit);
+ });
+ this.debug(this.pattern, set);
+ set = set.map(function(s, si, set2) {
+ return s.map(this.parse, this);
+ }, this);
+ this.debug(this.pattern, set);
+ set = set.filter(function(s) {
+ return s.indexOf(false) === -1;
+ });
+ this.debug(this.pattern, set);
+ this.set = set;
+ }
+ Minimatch.prototype.parseNegate = parseNegate;
+ function parseNegate() {
+ var pattern = this.pattern;
+ var negate = false;
+ var options = this.options;
+ var negateOffset = 0;
+ if (options.nonegate)
+ return;
+ for (var i = 0, l = pattern.length; i < l && pattern.charAt(i) === "!"; i++) {
+ negate = !negate;
+ negateOffset++;
+ }
+ if (negateOffset)
+ this.pattern = pattern.substr(negateOffset);
+ this.negate = negate;
+ }
+ minimatch.braceExpand = function(pattern, options) {
+ return braceExpand(pattern, options);
+ };
+ Minimatch.prototype.braceExpand = braceExpand;
+ function braceExpand(pattern, options) {
+ if (!options) {
+ if (this instanceof Minimatch) {
+ options = this.options;
+ } else {
+ options = {};
+ }
+ }
+ pattern = typeof pattern === "undefined" ? this.pattern : pattern;
+ if (typeof pattern === "undefined") {
+ throw new TypeError("undefined pattern");
+ }
+ if (options.nobrace || !pattern.match(/\{.*\}/)) {
+ return [pattern];
+ }
+ return expand(pattern);
+ }
+ Minimatch.prototype.parse = parse;
+ var SUBPARSE = {};
+ function parse(pattern, isSub) {
+ if (pattern.length > 1024 * 64) {
+ throw new TypeError("pattern is too long");
+ }
+ var options = this.options;
+ if (!options.noglobstar && pattern === "**")
+ return GLOBSTAR;
+ if (pattern === "")
+ return "";
+ var re = "";
+ var hasMagic = !!options.nocase;
+ var escaping = false;
+ var patternListStack = [];
+ var negativeLists = [];
+ var stateChar;
+ var inClass = false;
+ var reClassStart = -1;
+ var classStart = -1;
+ var patternStart = pattern.charAt(0) === "." ? "" : options.dot ? "(?!(?:^|\\/)\\.{1,2}(?:$|\\/))" : "(?!\\.)";
+ var self = this;
+ function clearStateChar() {
+ if (stateChar) {
+ switch (stateChar) {
+ case "*":
+ re += star;
+ hasMagic = true;
+ break;
+ case "?":
+ re += qmark;
+ hasMagic = true;
+ break;
+ default:
+ re += "\\" + stateChar;
+ break;
+ }
+ self.debug("clearStateChar %j %j", stateChar, re);
+ stateChar = false;
+ }
+ }
+ for (var i = 0, len = pattern.length, c; i < len && (c = pattern.charAt(i)); i++) {
+ this.debug("%s %s %s %j", pattern, i, re, c);
+ if (escaping && reSpecials[c]) {
+ re += "\\" + c;
+ escaping = false;
+ continue;
+ }
+ switch (c) {
+ case "/":
+ return false;
+ case "\\":
+ clearStateChar();
+ escaping = true;
+ continue;
+ case "?":
+ case "*":
+ case "+":
+ case "@":
+ case "!":
+ this.debug("%s %s %s %j <-- stateChar", pattern, i, re, c);
+ if (inClass) {
+ this.debug(" in class");
+ if (c === "!" && i === classStart + 1)
+ c = "^";
+ re += c;
+ continue;
+ }
+ self.debug("call clearStateChar %j", stateChar);
+ clearStateChar();
+ stateChar = c;
+ if (options.noext)
+ clearStateChar();
+ continue;
+ case "(":
+ if (inClass) {
+ re += "(";
+ continue;
+ }
+ if (!stateChar) {
+ re += "\\(";
+ continue;
+ }
+ patternListStack.push({
+ type: stateChar,
+ start: i - 1,
+ reStart: re.length,
+ open: plTypes[stateChar].open,
+ close: plTypes[stateChar].close
+ });
+ re += stateChar === "!" ? "(?:(?!(?:" : "(?:";
+ this.debug("plType %j %j", stateChar, re);
+ stateChar = false;
+ continue;
+ case ")":
+ if (inClass || !patternListStack.length) {
+ re += "\\)";
+ continue;
+ }
+ clearStateChar();
+ hasMagic = true;
+ var pl = patternListStack.pop();
+ re += pl.close;
+ if (pl.type === "!") {
+ negativeLists.push(pl);
+ }
+ pl.reEnd = re.length;
+ continue;
+ case "|":
+ if (inClass || !patternListStack.length || escaping) {
+ re += "\\|";
+ escaping = false;
+ continue;
+ }
+ clearStateChar();
+ re += "|";
+ continue;
+ case "[":
+ clearStateChar();
+ if (inClass) {
+ re += "\\" + c;
+ continue;
+ }
+ inClass = true;
+ classStart = i;
+ reClassStart = re.length;
+ re += c;
+ continue;
+ case "]":
+ if (i === classStart + 1 || !inClass) {
+ re += "\\" + c;
+ escaping = false;
+ continue;
+ }
+ if (inClass) {
+ var cs = pattern.substring(classStart + 1, i);
+ try {
+ RegExp("[" + cs + "]");
+ } catch (er) {
+ var sp = this.parse(cs, SUBPARSE);
+ re = re.substr(0, reClassStart) + "\\[" + sp[0] + "\\]";
+ hasMagic = hasMagic || sp[1];
+ inClass = false;
+ continue;
+ }
+ }
+ hasMagic = true;
+ inClass = false;
+ re += c;
+ continue;
+ default:
+ clearStateChar();
+ if (escaping) {
+ escaping = false;
+ } else if (reSpecials[c] && !(c === "^" && inClass)) {
+ re += "\\";
+ }
+ re += c;
+ }
+ }
+ if (inClass) {
+ cs = pattern.substr(classStart + 1);
+ sp = this.parse(cs, SUBPARSE);
+ re = re.substr(0, reClassStart) + "\\[" + sp[0];
+ hasMagic = hasMagic || sp[1];
+ }
+ for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
+ var tail = re.slice(pl.reStart + pl.open.length);
+ this.debug("setting tail", re, pl);
+ tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function(_, $1, $2) {
+ if (!$2) {
+ $2 = "\\";
+ }
+ return $1 + $1 + $2 + "|";
+ });
+ this.debug("tail=%j\n %s", tail, tail, pl, re);
+ var t = pl.type === "*" ? star : pl.type === "?" ? qmark : "\\" + pl.type;
+ hasMagic = true;
+ re = re.slice(0, pl.reStart) + t + "\\(" + tail;
+ }
+ clearStateChar();
+ if (escaping) {
+ re += "\\\\";
+ }
+ var addPatternStart = false;
+ switch (re.charAt(0)) {
+ case ".":
+ case "[":
+ case "(":
+ addPatternStart = true;
+ }
+ for (var n = negativeLists.length - 1; n > -1; n--) {
+ var nl = negativeLists[n];
+ var nlBefore = re.slice(0, nl.reStart);
+ var nlFirst = re.slice(nl.reStart, nl.reEnd - 8);
+ var nlLast = re.slice(nl.reEnd - 8, nl.reEnd);
+ var nlAfter = re.slice(nl.reEnd);
+ nlLast += nlAfter;
+ var openParensBefore = nlBefore.split("(").length - 1;
+ var cleanAfter = nlAfter;
+ for (i = 0; i < openParensBefore; i++) {
+ cleanAfter = cleanAfter.replace(/\)[+*?]?/, "");
+ }
+ nlAfter = cleanAfter;
+ var dollar = "";
+ if (nlAfter === "" && isSub !== SUBPARSE) {
+ dollar = "$";
+ }
+ var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast;
+ re = newRe;
+ }
+ if (re !== "" && hasMagic) {
+ re = "(?=.)" + re;
+ }
+ if (addPatternStart) {
+ re = patternStart + re;
+ }
+ if (isSub === SUBPARSE) {
+ return [re, hasMagic];
+ }
+ if (!hasMagic) {
+ return globUnescape(pattern);
+ }
+ var flags = options.nocase ? "i" : "";
+ try {
+ var regExp = new RegExp("^" + re + "$", flags);
+ } catch (er) {
+ return new RegExp("$.");
+ }
+ regExp._glob = pattern;
+ regExp._src = re;
+ return regExp;
+ }
+ minimatch.makeRe = function(pattern, options) {
+ return new Minimatch(pattern, options || {}).makeRe();
+ };
+ Minimatch.prototype.makeRe = makeRe;
+ function makeRe() {
+ if (this.regexp || this.regexp === false)
+ return this.regexp;
+ var set = this.set;
+ if (!set.length) {
+ this.regexp = false;
+ return this.regexp;
+ }
+ var options = this.options;
+ var twoStar = options.noglobstar ? star : options.dot ? twoStarDot : twoStarNoDot;
+ var flags = options.nocase ? "i" : "";
+ var re = set.map(function(pattern) {
+ return pattern.map(function(p) {
+ return p === GLOBSTAR ? twoStar : typeof p === "string" ? regExpEscape(p) : p._src;
+ }).join("\\/");
+ }).join("|");
+ re = "^(?:" + re + ")$";
+ if (this.negate)
+ re = "^(?!" + re + ").*$";
+ try {
+ this.regexp = new RegExp(re, flags);
+ } catch (ex) {
+ this.regexp = false;
+ }
+ return this.regexp;
+ }
+ minimatch.match = function(list, pattern, options) {
+ options = options || {};
+ var mm = new Minimatch(pattern, options);
+ list = list.filter(function(f) {
+ return mm.match(f);
+ });
+ if (mm.options.nonull && !list.length) {
+ list.push(pattern);
+ }
+ return list;
+ };
+ Minimatch.prototype.match = match;
+ function match(f, partial) {
+ this.debug("match", f, this.pattern);
+ if (this.comment)
+ return false;
+ if (this.empty)
+ return f === "";
+ if (f === "/" && partial)
+ return true;
+ var options = this.options;
+ if (path2.sep !== "/") {
+ f = f.split(path2.sep).join("/");
+ }
+ f = f.split(slashSplit);
+ this.debug(this.pattern, "split", f);
+ var set = this.set;
+ this.debug(this.pattern, "set", set);
+ var filename;
+ var i;
+ for (i = f.length - 1; i >= 0; i--) {
+ filename = f[i];
+ if (filename)
+ break;
+ }
+ for (i = 0; i < set.length; i++) {
+ var pattern = set[i];
+ var file = f;
+ if (options.matchBase && pattern.length === 1) {
+ file = [filename];
+ }
+ var hit = this.matchOne(file, pattern, partial);
+ if (hit) {
+ if (options.flipNegate)
+ return true;
+ return !this.negate;
+ }
+ }
+ if (options.flipNegate)
+ return false;
+ return this.negate;
+ }
+ Minimatch.prototype.matchOne = function(file, pattern, partial) {
+ var options = this.options;
+ this.debug("matchOne", { "this": this, file, pattern });
+ this.debug("matchOne", file.length, pattern.length);
+ for (var fi = 0, pi = 0, fl = file.length, pl = pattern.length; fi < fl && pi < pl; fi++, pi++) {
+ this.debug("matchOne loop");
+ var p = pattern[pi];
+ var f = file[fi];
+ this.debug(pattern, p, f);
+ if (p === false)
+ return false;
+ if (p === GLOBSTAR) {
+ this.debug("GLOBSTAR", [pattern, p, f]);
+ var fr = fi;
+ var pr = pi + 1;
+ if (pr === pl) {
+ this.debug("** at the end");
+ for (; fi < fl; fi++) {
+ if (file[fi] === "." || file[fi] === ".." || !options.dot && file[fi].charAt(0) === ".")
+ return false;
+ }
+ return true;
+ }
+ while (fr < fl) {
+ var swallowee = file[fr];
+ this.debug("\nglobstar while", file, fr, pattern, pr, swallowee);
+ if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
+ this.debug("globstar found match!", fr, fl, swallowee);
+ return true;
+ } else {
+ if (swallowee === "." || swallowee === ".." || !options.dot && swallowee.charAt(0) === ".") {
+ this.debug("dot detected!", file, fr, pattern, pr);
+ break;
+ }
+ this.debug("globstar swallow a segment, and continue");
+ fr++;
+ }
+ }
+ if (partial) {
+ this.debug("\n>>> no match, partial?", file, fr, pattern, pr);
+ if (fr === fl)
+ return true;
+ }
+ return false;
+ }
+ var hit;
+ if (typeof p === "string") {
+ if (options.nocase) {
+ hit = f.toLowerCase() === p.toLowerCase();
+ } else {
+ hit = f === p;
+ }
+ this.debug("string match", p, f, hit);
+ } else {
+ hit = f.match(p);
+ this.debug("pattern match", p, f, hit);
+ }
+ if (!hit)
+ return false;
+ }
+ if (fi === fl && pi === pl) {
+ return true;
+ } else if (fi === fl) {
+ return partial;
+ } else if (pi === pl) {
+ var emptyFileEnd = fi === fl - 1 && file[fi] === "";
+ return emptyFileEnd;
+ }
+ throw new Error("wtf?");
+ };
+ function globUnescape(s) {
+ return s.replace(/\\(.)/g, "$1");
+ }
+ function regExpEscape(s) {
+ return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
+ }
+ }
+});
+
+// pnp:inherits-npm-2.0.4-c66b3957a0-4a48a73384.zip/node_modules/inherits/inherits_browser.js
+var require_inherits_browser = __commonJS({
+ "pnp:inherits-npm-2.0.4-c66b3957a0-4a48a73384.zip/node_modules/inherits/inherits_browser.js"(exports, module2) {
+ if (typeof Object.create === "function") {
+ module2.exports = function inherits(ctor, superCtor) {
+ if (superCtor) {
+ ctor.super_ = superCtor;
+ ctor.prototype = Object.create(superCtor.prototype, {
+ constructor: {
+ value: ctor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ });
+ }
+ };
+ } else {
+ module2.exports = function inherits(ctor, superCtor) {
+ if (superCtor) {
+ ctor.super_ = superCtor;
+ var TempCtor = function() {
+ };
+ TempCtor.prototype = superCtor.prototype;
+ ctor.prototype = new TempCtor();
+ ctor.prototype.constructor = ctor;
+ }
+ };
+ }
+ }
+});
+
+// pnp:inherits-npm-2.0.4-c66b3957a0-4a48a73384.zip/node_modules/inherits/inherits.js
+var require_inherits = __commonJS({
+ "pnp:inherits-npm-2.0.4-c66b3957a0-4a48a73384.zip/node_modules/inherits/inherits.js"(exports, module2) {
+ try {
+ util = require("util");
+ if (typeof util.inherits !== "function")
+ throw "";
+ module2.exports = util.inherits;
+ } catch (e) {
+ module2.exports = require_inherits_browser();
+ }
+ var util;
+ }
+});
+
+// pnp:path-is-absolute-npm-1.0.1-31bc695ffd-060840f92c.zip/node_modules/path-is-absolute/index.js
+var require_path_is_absolute = __commonJS({
+ "pnp:path-is-absolute-npm-1.0.1-31bc695ffd-060840f92c.zip/node_modules/path-is-absolute/index.js"(exports, module2) {
+ "use strict";
+ function posix(path2) {
+ return path2.charAt(0) === "/";
+ }
+ function win32(path2) {
+ var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
+ var result = splitDeviceRe.exec(path2);
+ var device = result[1] || "";
+ var isUnc = Boolean(device && device.charAt(1) !== ":");
+ return Boolean(result[2] || isUnc);
+ }
+ module2.exports = process.platform === "win32" ? win32 : posix;
+ module2.exports.posix = posix;
+ module2.exports.win32 = win32;
+ }
+});
+
+// pnp:glob-npm-7.1.7-5698ad9c48-b61f48973b.zip/node_modules/glob/common.js
+var require_common = __commonJS({
+ "pnp:glob-npm-7.1.7-5698ad9c48-b61f48973b.zip/node_modules/glob/common.js"(exports) {
+ exports.setopts = setopts;
+ exports.ownProp = ownProp;
+ exports.makeAbs = makeAbs;
+ exports.finish = finish;
+ exports.mark = mark;
+ exports.isIgnored = isIgnored;
+ exports.childrenIgnored = childrenIgnored;
+ function ownProp(obj, field) {
+ return Object.prototype.hasOwnProperty.call(obj, field);
+ }
+ var path2 = require("path");
+ var minimatch = require_minimatch();
+ var isAbsolute = require_path_is_absolute();
+ var Minimatch = minimatch.Minimatch;
+ function alphasort(a, b) {
+ return a.localeCompare(b, "en");
+ }
+ function setupIgnores(self, options) {
+ self.ignore = options.ignore || [];
+ if (!Array.isArray(self.ignore))
+ self.ignore = [self.ignore];
+ if (self.ignore.length) {
+ self.ignore = self.ignore.map(ignoreMap);
+ }
+ }
+ function ignoreMap(pattern) {
+ var gmatcher = null;
+ if (pattern.slice(-3) === "/**") {
+ var gpattern = pattern.replace(/(\/\*\*)+$/, "");
+ gmatcher = new Minimatch(gpattern, { dot: true });
+ }
+ return {
+ matcher: new Minimatch(pattern, { dot: true }),
+ gmatcher
+ };
+ }
+ function setopts(self, pattern, options) {
+ if (!options)
+ options = {};
+ if (options.matchBase && pattern.indexOf("/") === -1) {
+ if (options.noglobstar) {
+ throw new Error("base matching requires globstar");
+ }
+ pattern = "**/" + pattern;
+ }
+ self.silent = !!options.silent;
+ self.pattern = pattern;
+ self.strict = options.strict !== false;
+ self.realpath = !!options.realpath;
+ self.realpathCache = options.realpathCache || Object.create(null);
+ self.follow = !!options.follow;
+ self.dot = !!options.dot;
+ self.mark = !!options.mark;
+ self.nodir = !!options.nodir;
+ if (self.nodir)
+ self.mark = true;
+ self.sync = !!options.sync;
+ self.nounique = !!options.nounique;
+ self.nonull = !!options.nonull;
+ self.nosort = !!options.nosort;
+ self.nocase = !!options.nocase;
+ self.stat = !!options.stat;
+ self.noprocess = !!options.noprocess;
+ self.absolute = !!options.absolute;
+ self.maxLength = options.maxLength || Infinity;
+ self.cache = options.cache || Object.create(null);
+ self.statCache = options.statCache || Object.create(null);
+ self.symlinks = options.symlinks || Object.create(null);
+ setupIgnores(self, options);
+ self.changedCwd = false;
+ var cwd = process.cwd();
+ if (!ownProp(options, "cwd"))
+ self.cwd = cwd;
+ else {
+ self.cwd = path2.resolve(options.cwd);
+ self.changedCwd = self.cwd !== cwd;
+ }
+ self.root = options.root || path2.resolve(self.cwd, "/");
+ self.root = path2.resolve(self.root);
+ if (process.platform === "win32")
+ self.root = self.root.replace(/\\/g, "/");
+ self.cwdAbs = isAbsolute(self.cwd) ? self.cwd : makeAbs(self, self.cwd);
+ if (process.platform === "win32")
+ self.cwdAbs = self.cwdAbs.replace(/\\/g, "/");
+ self.nomount = !!options.nomount;
+ options.nonegate = true;
+ options.nocomment = true;
+ self.minimatch = new Minimatch(pattern, options);
+ self.options = self.minimatch.options;
+ }
+ function finish(self) {
+ var nou = self.nounique;
+ var all = nou ? [] : Object.create(null);
+ for (var i = 0, l = self.matches.length; i < l; i++) {
+ var matches = self.matches[i];
+ if (!matches || Object.keys(matches).length === 0) {
+ if (self.nonull) {
+ var literal = self.minimatch.globSet[i];
+ if (nou)
+ all.push(literal);
+ else
+ all[literal] = true;
+ }
+ } else {
+ var m = Object.keys(matches);
+ if (nou)
+ all.push.apply(all, m);
+ else
+ m.forEach(function(m2) {
+ all[m2] = true;
+ });
+ }
+ }
+ if (!nou)
+ all = Object.keys(all);
+ if (!self.nosort)
+ all = all.sort(alphasort);
+ if (self.mark) {
+ for (var i = 0; i < all.length; i++) {
+ all[i] = self._mark(all[i]);
+ }
+ if (self.nodir) {
+ all = all.filter(function(e) {
+ var notDir = !/\/$/.test(e);
+ var c = self.cache[e] || self.cache[makeAbs(self, e)];
+ if (notDir && c)
+ notDir = c !== "DIR" && !Array.isArray(c);
+ return notDir;
+ });
+ }
+ }
+ if (self.ignore.length)
+ all = all.filter(function(m2) {
+ return !isIgnored(self, m2);
+ });
+ self.found = all;
+ }
+ function mark(self, p) {
+ var abs = makeAbs(self, p);
+ var c = self.cache[abs];
+ var m = p;
+ if (c) {
+ var isDir = c === "DIR" || Array.isArray(c);
+ var slash = p.slice(-1) === "/";
+ if (isDir && !slash)
+ m += "/";
+ else if (!isDir && slash)
+ m = m.slice(0, -1);
+ if (m !== p) {
+ var mabs = makeAbs(self, m);
+ self.statCache[mabs] = self.statCache[abs];
+ self.cache[mabs] = self.cache[abs];
+ }
+ }
+ return m;
+ }
+ function makeAbs(self, f) {
+ var abs = f;
+ if (f.charAt(0) === "/") {
+ abs = path2.join(self.root, f);
+ } else if (isAbsolute(f) || f === "") {
+ abs = f;
+ } else if (self.changedCwd) {
+ abs = path2.resolve(self.cwd, f);
+ } else {
+ abs = path2.resolve(f);
+ }
+ if (process.platform === "win32")
+ abs = abs.replace(/\\/g, "/");
+ return abs;
+ }
+ function isIgnored(self, path3) {
+ if (!self.ignore.length)
+ return false;
+ return self.ignore.some(function(item) {
+ return item.matcher.match(path3) || !!(item.gmatcher && item.gmatcher.match(path3));
+ });
+ }
+ function childrenIgnored(self, path3) {
+ if (!self.ignore.length)
+ return false;
+ return self.ignore.some(function(item) {
+ return !!(item.gmatcher && item.gmatcher.match(path3));
+ });
+ }
+ }
+});
+
+// pnp:glob-npm-7.1.7-5698ad9c48-b61f48973b.zip/node_modules/glob/sync.js
+var require_sync = __commonJS({
+ "pnp:glob-npm-7.1.7-5698ad9c48-b61f48973b.zip/node_modules/glob/sync.js"(exports, module2) {
+ module2.exports = globSync;
+ globSync.GlobSync = GlobSync;
+ var fs4 = require("fs");
+ var rp = require_fs();
+ var minimatch = require_minimatch();
+ var Minimatch = minimatch.Minimatch;
+ var Glob2 = require_glob().Glob;
+ var util = require("util");
+ var path2 = require("path");
+ var assert = require("assert");
+ var isAbsolute = require_path_is_absolute();
+ var common = require_common();
+ var setopts = common.setopts;
+ var ownProp = common.ownProp;
+ var childrenIgnored = common.childrenIgnored;
+ var isIgnored = common.isIgnored;
+ function globSync(pattern, options) {
+ if (typeof options === "function" || arguments.length === 3)
+ throw new TypeError("callback provided to sync glob\nSee: https://github.com/isaacs/node-glob/issues/167");
+ return new GlobSync(pattern, options).found;
+ }
+ function GlobSync(pattern, options) {
+ if (!pattern)
+ throw new Error("must provide pattern");
+ if (typeof options === "function" || arguments.length === 3)
+ throw new TypeError("callback provided to sync glob\nSee: https://github.com/isaacs/node-glob/issues/167");
+ if (!(this instanceof GlobSync))
+ return new GlobSync(pattern, options);
+ setopts(this, pattern, options);
+ if (this.noprocess)
+ return this;
+ var n = this.minimatch.set.length;
+ this.matches = new Array(n);
+ for (var i = 0; i < n; i++) {
+ this._process(this.minimatch.set[i], i, false);
+ }
+ this._finish();
+ }
+ GlobSync.prototype._finish = function() {
+ assert(this instanceof GlobSync);
+ if (this.realpath) {
+ var self = this;
+ this.matches.forEach(function(matchset, index) {
+ var set = self.matches[index] = Object.create(null);
+ for (var p in matchset) {
+ try {
+ p = self._makeAbs(p);
+ var real = rp.realpathSync(p, self.realpathCache);
+ set[real] = true;
+ } catch (er) {
+ if (er.syscall === "stat")
+ set[self._makeAbs(p)] = true;
+ else
+ throw er;
+ }
+ }
+ });
+ }
+ common.finish(this);
+ };
+ GlobSync.prototype._process = function(pattern, index, inGlobStar) {
+ assert(this instanceof GlobSync);
+ var n = 0;
+ while (typeof pattern[n] === "string") {
+ n++;
+ }
+ var prefix;
+ switch (n) {
+ case pattern.length:
+ this._processSimple(pattern.join("/"), index);
+ return;
+ case 0:
+ prefix = null;
+ break;
+ default:
+ prefix = pattern.slice(0, n).join("/");
+ break;
+ }
+ var remain = pattern.slice(n);
+ var read;
+ if (prefix === null)
+ read = ".";
+ else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) {
+ if (!prefix || !isAbsolute(prefix))
+ prefix = "/" + prefix;
+ read = prefix;
+ } else
+ read = prefix;
+ var abs = this._makeAbs(read);
+ if (childrenIgnored(this, read))
+ return;
+ var isGlobStar = remain[0] === minimatch.GLOBSTAR;
+ if (isGlobStar)
+ this._processGlobStar(prefix, read, abs, remain, index, inGlobStar);
+ else
+ this._processReaddir(prefix, read, abs, remain, index, inGlobStar);
+ };
+ GlobSync.prototype._processReaddir = function(prefix, read, abs, remain, index, inGlobStar) {
+ var entries = this._readdir(abs, inGlobStar);
+ if (!entries)
+ return;
+ var pn = remain[0];
+ var negate = !!this.minimatch.negate;
+ var rawGlob = pn._glob;
+ var dotOk = this.dot || rawGlob.charAt(0) === ".";
+ var matchedEntries = [];
+ for (var i = 0; i < entries.length; i++) {
+ var e = entries[i];
+ if (e.charAt(0) !== "." || dotOk) {
+ var m;
+ if (negate && !prefix) {
+ m = !e.match(pn);
+ } else {
+ m = e.match(pn);
+ }
+ if (m)
+ matchedEntries.push(e);
+ }
+ }
+ var len = matchedEntries.length;
+ if (len === 0)
+ return;
+ if (remain.length === 1 && !this.mark && !this.stat) {
+ if (!this.matches[index])
+ this.matches[index] = Object.create(null);
+ for (var i = 0; i < len; i++) {
+ var e = matchedEntries[i];
+ if (prefix) {
+ if (prefix.slice(-1) !== "/")
+ e = prefix + "/" + e;
+ else
+ e = prefix + e;
+ }
+ if (e.charAt(0) === "/" && !this.nomount) {
+ e = path2.join(this.root, e);
+ }
+ this._emitMatch(index, e);
+ }
+ return;
+ }
+ remain.shift();
+ for (var i = 0; i < len; i++) {
+ var e = matchedEntries[i];
+ var newPattern;
+ if (prefix)
+ newPattern = [prefix, e];
+ else
+ newPattern = [e];
+ this._process(newPattern.concat(remain), index, inGlobStar);
+ }
+ };
+ GlobSync.prototype._emitMatch = function(index, e) {
+ if (isIgnored(this, e))
+ return;
+ var abs = this._makeAbs(e);
+ if (this.mark)
+ e = this._mark(e);
+ if (this.absolute) {
+ e = abs;
+ }
+ if (this.matches[index][e])
+ return;
+ if (this.nodir) {
+ var c = this.cache[abs];
+ if (c === "DIR" || Array.isArray(c))
+ return;
+ }
+ this.matches[index][e] = true;
+ if (this.stat)
+ this._stat(e);
+ };
+ GlobSync.prototype._readdirInGlobStar = function(abs) {
+ if (this.follow)
+ return this._readdir(abs, false);
+ var entries;
+ var lstat;
+ var stat;
+ try {
+ lstat = fs4.lstatSync(abs);
+ } catch (er) {
+ if (er.code === "ENOENT") {
+ return null;
+ }
+ }
+ var isSym = lstat && lstat.isSymbolicLink();
+ this.symlinks[abs] = isSym;
+ if (!isSym && lstat && !lstat.isDirectory())
+ this.cache[abs] = "FILE";
+ else
+ entries = this._readdir(abs, false);
+ return entries;
+ };
+ GlobSync.prototype._readdir = function(abs, inGlobStar) {
+ var entries;
+ if (inGlobStar && !ownProp(this.symlinks, abs))
+ return this._readdirInGlobStar(abs);
+ if (ownProp(this.cache, abs)) {
+ var c = this.cache[abs];
+ if (!c || c === "FILE")
+ return null;
+ if (Array.isArray(c))
+ return c;
+ }
+ try {
+ return this._readdirEntries(abs, fs4.readdirSync(abs));
+ } catch (er) {
+ this._readdirError(abs, er);
+ return null;
+ }
+ };
+ GlobSync.prototype._readdirEntries = function(abs, entries) {
+ if (!this.mark && !this.stat) {
+ for (var i = 0; i < entries.length; i++) {
+ var e = entries[i];
+ if (abs === "/")
+ e = abs + e;
+ else
+ e = abs + "/" + e;
+ this.cache[e] = true;
+ }
+ }
+ this.cache[abs] = entries;
+ return entries;
+ };
+ GlobSync.prototype._readdirError = function(f, er) {
+ switch (er.code) {
+ case "ENOTSUP":
+ case "ENOTDIR":
+ var abs = this._makeAbs(f);
+ this.cache[abs] = "FILE";
+ if (abs === this.cwdAbs) {
+ var error = new Error(er.code + " invalid cwd " + this.cwd);
+ error.path = this.cwd;
+ error.code = er.code;
+ throw error;
+ }
+ break;
+ case "ENOENT":
+ case "ELOOP":
+ case "ENAMETOOLONG":
+ case "UNKNOWN":
+ this.cache[this._makeAbs(f)] = false;
+ break;
+ default:
+ this.cache[this._makeAbs(f)] = false;
+ if (this.strict)
+ throw er;
+ if (!this.silent)
+ console.error("glob error", er);
+ break;
+ }
+ };
+ GlobSync.prototype._processGlobStar = function(prefix, read, abs, remain, index, inGlobStar) {
+ var entries = this._readdir(abs, inGlobStar);
+ if (!entries)
+ return;
+ var remainWithoutGlobStar = remain.slice(1);
+ var gspref = prefix ? [prefix] : [];
+ var noGlobStar = gspref.concat(remainWithoutGlobStar);
+ this._process(noGlobStar, index, false);
+ var len = entries.length;
+ var isSym = this.symlinks[abs];
+ if (isSym && inGlobStar)
+ return;
+ for (var i = 0; i < len; i++) {
+ var e = entries[i];
+ if (e.charAt(0) === "." && !this.dot)
+ continue;
+ var instead = gspref.concat(entries[i], remainWithoutGlobStar);
+ this._process(instead, index, true);
+ var below = gspref.concat(entries[i], remain);
+ this._process(below, index, true);
+ }
+ };
+ GlobSync.prototype._processSimple = function(prefix, index) {
+ var exists = this._stat(prefix);
+ if (!this.matches[index])
+ this.matches[index] = Object.create(null);
+ if (!exists)
+ return;
+ if (prefix && isAbsolute(prefix) && !this.nomount) {
+ var trail = /[\/\\]$/.test(prefix);
+ if (prefix.charAt(0) === "/") {
+ prefix = path2.join(this.root, prefix);
+ } else {
+ prefix = path2.resolve(this.root, prefix);
+ if (trail)
+ prefix += "/";
+ }
+ }
+ if (process.platform === "win32")
+ prefix = prefix.replace(/\\/g, "/");
+ this._emitMatch(index, prefix);
+ };
+ GlobSync.prototype._stat = function(f) {
+ var abs = this._makeAbs(f);
+ var needDir = f.slice(-1) === "/";
+ if (f.length > this.maxLength)
+ return false;
+ if (!this.stat && ownProp(this.cache, abs)) {
+ var c = this.cache[abs];
+ if (Array.isArray(c))
+ c = "DIR";
+ if (!needDir || c === "DIR")
+ return c;
+ if (needDir && c === "FILE")
+ return false;
+ }
+ var exists;
+ var stat = this.statCache[abs];
+ if (!stat) {
+ var lstat;
+ try {
+ lstat = fs4.lstatSync(abs);
+ } catch (er) {
+ if (er && (er.code === "ENOENT" || er.code === "ENOTDIR")) {
+ this.statCache[abs] = false;
+ return false;
+ }
+ }
+ if (lstat && lstat.isSymbolicLink()) {
+ try {
+ stat = fs4.statSync(abs);
+ } catch (er) {
+ stat = lstat;
+ }
+ } else {
+ stat = lstat;
+ }
+ }
+ this.statCache[abs] = stat;
+ var c = true;
+ if (stat)
+ c = stat.isDirectory() ? "DIR" : "FILE";
+ this.cache[abs] = this.cache[abs] || c;
+ if (needDir && c === "FILE")
+ return false;
+ return c;
+ };
+ GlobSync.prototype._mark = function(p) {
+ return common.mark(this, p);
+ };
+ GlobSync.prototype._makeAbs = function(f) {
+ return common.makeAbs(this, f);
+ };
+ }
+});
+
+// pnp:wrappy-npm-1.0.2-916de4d4b3-159da4805f.zip/node_modules/wrappy/wrappy.js
+var require_wrappy = __commonJS({
+ "pnp:wrappy-npm-1.0.2-916de4d4b3-159da4805f.zip/node_modules/wrappy/wrappy.js"(exports, module2) {
+ module2.exports = wrappy;
+ function wrappy(fn, cb) {
+ if (fn && cb)
+ return wrappy(fn)(cb);
+ if (typeof fn !== "function")
+ throw new TypeError("need wrapper function");
+ Object.keys(fn).forEach(function(k) {
+ wrapper[k] = fn[k];
+ });
+ return wrapper;
+ function wrapper() {
+ var args = new Array(arguments.length);
+ for (var i = 0; i < args.length; i++) {
+ args[i] = arguments[i];
+ }
+ var ret = fn.apply(this, args);
+ var cb2 = args[args.length - 1];
+ if (typeof ret === "function" && ret !== cb2) {
+ Object.keys(cb2).forEach(function(k) {
+ ret[k] = cb2[k];
+ });
+ }
+ return ret;
+ }
+ }
+ }
+});
+
+// pnp:once-npm-1.4.0-ccf03ef07a-cd0a885013.zip/node_modules/once/once.js
+var require_once = __commonJS({
+ "pnp:once-npm-1.4.0-ccf03ef07a-cd0a885013.zip/node_modules/once/once.js"(exports, module2) {
+ var wrappy = require_wrappy();
+ module2.exports = wrappy(once);
+ module2.exports.strict = wrappy(onceStrict);
+ once.proto = once(function() {
+ Object.defineProperty(Function.prototype, "once", {
+ value: function() {
+ return once(this);
+ },
+ configurable: true
+ });
+ Object.defineProperty(Function.prototype, "onceStrict", {
+ value: function() {
+ return onceStrict(this);
+ },
+ configurable: true
+ });
+ });
+ function once(fn) {
+ var f = function() {
+ if (f.called)
+ return f.value;
+ f.called = true;
+ return f.value = fn.apply(this, arguments);
+ };
+ f.called = false;
+ return f;
+ }
+ function onceStrict(fn) {
+ var f = function() {
+ if (f.called)
+ throw new Error(f.onceError);
+ f.called = true;
+ return f.value = fn.apply(this, arguments);
+ };
+ var name = fn.name || "Function wrapped with `once`";
+ f.onceError = name + " shouldn't be called more than once";
+ f.called = false;
+ return f;
+ }
+ }
+});
+
+// pnp:inflight-npm-1.0.6-ccedb4b908-f4f76aa072.zip/node_modules/inflight/inflight.js
+var require_inflight = __commonJS({
+ "pnp:inflight-npm-1.0.6-ccedb4b908-f4f76aa072.zip/node_modules/inflight/inflight.js"(exports, module2) {
+ var wrappy = require_wrappy();
+ var reqs = Object.create(null);
+ var once = require_once();
+ module2.exports = wrappy(inflight);
+ function inflight(key, cb) {
+ if (reqs[key]) {
+ reqs[key].push(cb);
+ return null;
+ } else {
+ reqs[key] = [cb];
+ return makeres(key);
+ }
+ }
+ function makeres(key) {
+ return once(function RES() {
+ var cbs = reqs[key];
+ var len = cbs.length;
+ var args = slice(arguments);
+ try {
+ for (var i = 0; i < len; i++) {
+ cbs[i].apply(null, args);
+ }
+ } finally {
+ if (cbs.length > len) {
+ cbs.splice(0, len);
+ process.nextTick(function() {
+ RES.apply(null, args);
+ });
+ } else {
+ delete reqs[key];
+ }
+ }
+ });
+ }
+ function slice(args) {
+ var length = args.length;
+ var array = [];
+ for (var i = 0; i < length; i++)
+ array[i] = args[i];
+ return array;
+ }
+ }
+});
+
+// pnp:glob-npm-7.1.7-5698ad9c48-b61f48973b.zip/node_modules/glob/glob.js
+var require_glob = __commonJS({
+ "pnp:glob-npm-7.1.7-5698ad9c48-b61f48973b.zip/node_modules/glob/glob.js"(exports, module2) {
+ module2.exports = glob2;
+ var fs4 = require("fs");
+ var rp = require_fs();
+ var minimatch = require_minimatch();
+ var Minimatch = minimatch.Minimatch;
+ var inherits = require_inherits();
+ var EE = require("events").EventEmitter;
+ var path2 = require("path");
+ var assert = require("assert");
+ var isAbsolute = require_path_is_absolute();
+ var globSync = require_sync();
+ var common = require_common();
+ var setopts = common.setopts;
+ var ownProp = common.ownProp;
+ var inflight = require_inflight();
+ var util = require("util");
+ var childrenIgnored = common.childrenIgnored;
+ var isIgnored = common.isIgnored;
+ var once = require_once();
+ function glob2(pattern, options, cb) {
+ if (typeof options === "function")
+ cb = options, options = {};
+ if (!options)
+ options = {};
+ if (options.sync) {
+ if (cb)
+ throw new TypeError("callback provided to sync glob");
+ return globSync(pattern, options);
+ }
+ return new Glob2(pattern, options, cb);
+ }
+ glob2.sync = globSync;
+ var GlobSync = glob2.GlobSync = globSync.GlobSync;
+ glob2.glob = glob2;
+ function extend(origin, add) {
+ if (add === null || typeof add !== "object") {
+ return origin;
+ }
+ var keys = Object.keys(add);
+ var i = keys.length;
+ while (i--) {
+ origin[keys[i]] = add[keys[i]];
+ }
+ return origin;
+ }
+ glob2.hasMagic = function(pattern, options_) {
+ var options = extend({}, options_);
+ options.noprocess = true;
+ var g = new Glob2(pattern, options);
+ var set = g.minimatch.set;
+ if (!pattern)
+ return false;
+ if (set.length > 1)
+ return true;
+ for (var j = 0; j < set[0].length; j++) {
+ if (typeof set[0][j] !== "string")
+ return true;
+ }
+ return false;
+ };
+ glob2.Glob = Glob2;
+ inherits(Glob2, EE);
+ function Glob2(pattern, options, cb) {
+ if (typeof options === "function") {
+ cb = options;
+ options = null;
+ }
+ if (options && options.sync) {
+ if (cb)
+ throw new TypeError("callback provided to sync glob");
+ return new GlobSync(pattern, options);
+ }
+ if (!(this instanceof Glob2))
+ return new Glob2(pattern, options, cb);
+ setopts(this, pattern, options);
+ this._didRealPath = false;
+ var n = this.minimatch.set.length;
+ this.matches = new Array(n);
+ if (typeof cb === "function") {
+ cb = once(cb);
+ this.on("error", cb);
+ this.on("end", function(matches) {
+ cb(null, matches);
+ });
+ }
+ var self = this;
+ this._processing = 0;
+ this._emitQueue = [];
+ this._processQueue = [];
+ this.paused = false;
+ if (this.noprocess)
+ return this;
+ if (n === 0)
+ return done();
+ var sync = true;
+ for (var i = 0; i < n; i++) {
+ this._process(this.minimatch.set[i], i, false, done);
+ }
+ sync = false;
+ function done() {
+ --self._processing;
+ if (self._processing <= 0) {
+ if (sync) {
+ process.nextTick(function() {
+ self._finish();
+ });
+ } else {
+ self._finish();
+ }
+ }
+ }
+ }
+ Glob2.prototype._finish = function() {
+ assert(this instanceof Glob2);
+ if (this.aborted)
+ return;
+ if (this.realpath && !this._didRealpath)
+ return this._realpath();
+ common.finish(this);
+ this.emit("end", this.found);
+ };
+ Glob2.prototype._realpath = function() {
+ if (this._didRealpath)
+ return;
+ this._didRealpath = true;
+ var n = this.matches.length;
+ if (n === 0)
+ return this._finish();
+ var self = this;
+ for (var i = 0; i < this.matches.length; i++)
+ this._realpathSet(i, next);
+ function next() {
+ if (--n === 0)
+ self._finish();
+ }
+ };
+ Glob2.prototype._realpathSet = function(index, cb) {
+ var matchset = this.matches[index];
+ if (!matchset)
+ return cb();
+ var found = Object.keys(matchset);
+ var self = this;
+ var n = found.length;
+ if (n === 0)
+ return cb();
+ var set = this.matches[index] = Object.create(null);
+ found.forEach(function(p, i) {
+ p = self._makeAbs(p);
+ rp.realpath(p, self.realpathCache, function(er, real) {
+ if (!er)
+ set[real] = true;
+ else if (er.syscall === "stat")
+ set[p] = true;
+ else
+ self.emit("error", er);
+ if (--n === 0) {
+ self.matches[index] = set;
+ cb();
+ }
+ });
+ });
+ };
+ Glob2.prototype._mark = function(p) {
+ return common.mark(this, p);
+ };
+ Glob2.prototype._makeAbs = function(f) {
+ return common.makeAbs(this, f);
+ };
+ Glob2.prototype.abort = function() {
+ this.aborted = true;
+ this.emit("abort");
+ };
+ Glob2.prototype.pause = function() {
+ if (!this.paused) {
+ this.paused = true;
+ this.emit("pause");
+ }
+ };
+ Glob2.prototype.resume = function() {
+ if (this.paused) {
+ this.emit("resume");
+ this.paused = false;
+ if (this._emitQueue.length) {
+ var eq = this._emitQueue.slice(0);
+ this._emitQueue.length = 0;
+ for (var i = 0; i < eq.length; i++) {
+ var e = eq[i];
+ this._emitMatch(e[0], e[1]);
+ }
+ }
+ if (this._processQueue.length) {
+ var pq = this._processQueue.slice(0);
+ this._processQueue.length = 0;
+ for (var i = 0; i < pq.length; i++) {
+ var p = pq[i];
+ this._processing--;
+ this._process(p[0], p[1], p[2], p[3]);
+ }
+ }
+ }
+ };
+ Glob2.prototype._process = function(pattern, index, inGlobStar, cb) {
+ assert(this instanceof Glob2);
+ assert(typeof cb === "function");
+ if (this.aborted)
+ return;
+ this._processing++;
+ if (this.paused) {
+ this._processQueue.push([pattern, index, inGlobStar, cb]);
+ return;
+ }
+ var n = 0;
+ while (typeof pattern[n] === "string") {
+ n++;
+ }
+ var prefix;
+ switch (n) {
+ case pattern.length:
+ this._processSimple(pattern.join("/"), index, cb);
+ return;
+ case 0:
+ prefix = null;
+ break;
+ default:
+ prefix = pattern.slice(0, n).join("/");
+ break;
+ }
+ var remain = pattern.slice(n);
+ var read;
+ if (prefix === null)
+ read = ".";
+ else if (isAbsolute(prefix) || isAbsolute(pattern.join("/"))) {
+ if (!prefix || !isAbsolute(prefix))
+ prefix = "/" + prefix;
+ read = prefix;
+ } else
+ read = prefix;
+ var abs = this._makeAbs(read);
+ if (childrenIgnored(this, read))
+ return cb();
+ var isGlobStar = remain[0] === minimatch.GLOBSTAR;
+ if (isGlobStar)
+ this._processGlobStar(prefix, read, abs, remain, index, inGlobStar, cb);
+ else
+ this._processReaddir(prefix, read, abs, remain, index, inGlobStar, cb);
+ };
+ Glob2.prototype._processReaddir = function(prefix, read, abs, remain, index, inGlobStar, cb) {
+ var self = this;
+ this._readdir(abs, inGlobStar, function(er, entries) {
+ return self._processReaddir2(prefix, read, abs, remain, index, inGlobStar, entries, cb);
+ });
+ };
+ Glob2.prototype._processReaddir2 = function(prefix, read, abs, remain, index, inGlobStar, entries, cb) {
+ if (!entries)
+ return cb();
+ var pn = remain[0];
+ var negate = !!this.minimatch.negate;
+ var rawGlob = pn._glob;
+ var dotOk = this.dot || rawGlob.charAt(0) === ".";
+ var matchedEntries = [];
+ for (var i = 0; i < entries.length; i++) {
+ var e = entries[i];
+ if (e.charAt(0) !== "." || dotOk) {
+ var m;
+ if (negate && !prefix) {
+ m = !e.match(pn);
+ } else {
+ m = e.match(pn);
+ }
+ if (m)
+ matchedEntries.push(e);
+ }
+ }
+ var len = matchedEntries.length;
+ if (len === 0)
+ return cb();
+ if (remain.length === 1 && !this.mark && !this.stat) {
+ if (!this.matches[index])
+ this.matches[index] = Object.create(null);
+ for (var i = 0; i < len; i++) {
+ var e = matchedEntries[i];
+ if (prefix) {
+ if (prefix !== "/")
+ e = prefix + "/" + e;
+ else
+ e = prefix + e;
+ }
+ if (e.charAt(0) === "/" && !this.nomount) {
+ e = path2.join(this.root, e);
+ }
+ this._emitMatch(index, e);
+ }
+ return cb();
+ }
+ remain.shift();
+ for (var i = 0; i < len; i++) {
+ var e = matchedEntries[i];
+ var newPattern;
+ if (prefix) {
+ if (prefix !== "/")
+ e = prefix + "/" + e;
+ else
+ e = prefix + e;
+ }
+ this._process([e].concat(remain), index, inGlobStar, cb);
+ }
+ cb();
+ };
+ Glob2.prototype._emitMatch = function(index, e) {
+ if (this.aborted)
+ return;
+ if (isIgnored(this, e))
+ return;
+ if (this.paused) {
+ this._emitQueue.push([index, e]);
+ return;
+ }
+ var abs = isAbsolute(e) ? e : this._makeAbs(e);
+ if (this.mark)
+ e = this._mark(e);
+ if (this.absolute)
+ e = abs;
+ if (this.matches[index][e])
+ return;
+ if (this.nodir) {
+ var c = this.cache[abs];
+ if (c === "DIR" || Array.isArray(c))
+ return;
+ }
+ this.matches[index][e] = true;
+ var st = this.statCache[abs];
+ if (st)
+ this.emit("stat", e, st);
+ this.emit("match", e);
+ };
+ Glob2.prototype._readdirInGlobStar = function(abs, cb) {
+ if (this.aborted)
+ return;
+ if (this.follow)
+ return this._readdir(abs, false, cb);
+ var lstatkey = "lstat\0" + abs;
+ var self = this;
+ var lstatcb = inflight(lstatkey, lstatcb_);
+ if (lstatcb)
+ fs4.lstat(abs, lstatcb);
+ function lstatcb_(er, lstat) {
+ if (er && er.code === "ENOENT")
+ return cb();
+ var isSym = lstat && lstat.isSymbolicLink();
+ self.symlinks[abs] = isSym;
+ if (!isSym && lstat && !lstat.isDirectory()) {
+ self.cache[abs] = "FILE";
+ cb();
+ } else
+ self._readdir(abs, false, cb);
+ }
+ };
+ Glob2.prototype._readdir = function(abs, inGlobStar, cb) {
+ if (this.aborted)
+ return;
+ cb = inflight("readdir\0" + abs + "\0" + inGlobStar, cb);
+ if (!cb)
+ return;
+ if (inGlobStar && !ownProp(this.symlinks, abs))
+ return this._readdirInGlobStar(abs, cb);
+ if (ownProp(this.cache, abs)) {
+ var c = this.cache[abs];
+ if (!c || c === "FILE")
+ return cb();
+ if (Array.isArray(c))
+ return cb(null, c);
+ }
+ var self = this;
+ fs4.readdir(abs, readdirCb(this, abs, cb));
+ };
+ function readdirCb(self, abs, cb) {
+ return function(er, entries) {
+ if (er)
+ self._readdirError(abs, er, cb);
+ else
+ self._readdirEntries(abs, entries, cb);
+ };
+ }
+ Glob2.prototype._readdirEntries = function(abs, entries, cb) {
+ if (this.aborted)
+ return;
+ if (!this.mark && !this.stat) {
+ for (var i = 0; i < entries.length; i++) {
+ var e = entries[i];
+ if (abs === "/")
+ e = abs + e;
+ else
+ e = abs + "/" + e;
+ this.cache[e] = true;
+ }
+ }
+ this.cache[abs] = entries;
+ return cb(null, entries);
+ };
+ Glob2.prototype._readdirError = function(f, er, cb) {
+ if (this.aborted)
+ return;
+ switch (er.code) {
+ case "ENOTSUP":
+ case "ENOTDIR":
+ var abs = this._makeAbs(f);
+ this.cache[abs] = "FILE";
+ if (abs === this.cwdAbs) {
+ var error = new Error(er.code + " invalid cwd " + this.cwd);
+ error.path = this.cwd;
+ error.code = er.code;
+ this.emit("error", error);
+ this.abort();
+ }
+ break;
+ case "ENOENT":
+ case "ELOOP":
+ case "ENAMETOOLONG":
+ case "UNKNOWN":
+ this.cache[this._makeAbs(f)] = false;
+ break;
+ default:
+ this.cache[this._makeAbs(f)] = false;
+ if (this.strict) {
+ this.emit("error", er);
+ this.abort();
+ }
+ if (!this.silent)
+ console.error("glob error", er);
+ break;
+ }
+ return cb();
+ };
+ Glob2.prototype._processGlobStar = function(prefix, read, abs, remain, index, inGlobStar, cb) {
+ var self = this;
+ this._readdir(abs, inGlobStar, function(er, entries) {
+ self._processGlobStar2(prefix, read, abs, remain, index, inGlobStar, entries, cb);
+ });
+ };
+ Glob2.prototype._processGlobStar2 = function(prefix, read, abs, remain, index, inGlobStar, entries, cb) {
+ if (!entries)
+ return cb();
+ var remainWithoutGlobStar = remain.slice(1);
+ var gspref = prefix ? [prefix] : [];
+ var noGlobStar = gspref.concat(remainWithoutGlobStar);
+ this._process(noGlobStar, index, false, cb);
+ var isSym = this.symlinks[abs];
+ var len = entries.length;
+ if (isSym && inGlobStar)
+ return cb();
+ for (var i = 0; i < len; i++) {
+ var e = entries[i];
+ if (e.charAt(0) === "." && !this.dot)
+ continue;
+ var instead = gspref.concat(entries[i], remainWithoutGlobStar);
+ this._process(instead, index, true, cb);
+ var below = gspref.concat(entries[i], remain);
+ this._process(below, index, true, cb);
+ }
+ cb();
+ };
+ Glob2.prototype._processSimple = function(prefix, index, cb) {
+ var self = this;
+ this._stat(prefix, function(er, exists) {
+ self._processSimple2(prefix, index, er, exists, cb);
+ });
+ };
+ Glob2.prototype._processSimple2 = function(prefix, index, er, exists, cb) {
+ if (!this.matches[index])
+ this.matches[index] = Object.create(null);
+ if (!exists)
+ return cb();
+ if (prefix && isAbsolute(prefix) && !this.nomount) {
+ var trail = /[\/\\]$/.test(prefix);
+ if (prefix.charAt(0) === "/") {
+ prefix = path2.join(this.root, prefix);
+ } else {
+ prefix = path2.resolve(this.root, prefix);
+ if (trail)
+ prefix += "/";
+ }
+ }
+ if (process.platform === "win32")
+ prefix = prefix.replace(/\\/g, "/");
+ this._emitMatch(index, prefix);
+ cb();
+ };
+ Glob2.prototype._stat = function(f, cb) {
+ var abs = this._makeAbs(f);
+ var needDir = f.slice(-1) === "/";
+ if (f.length > this.maxLength)
+ return cb();
+ if (!this.stat && ownProp(this.cache, abs)) {
+ var c = this.cache[abs];
+ if (Array.isArray(c))
+ c = "DIR";
+ if (!needDir || c === "DIR")
+ return cb(null, c);
+ if (needDir && c === "FILE")
+ return cb();
+ }
+ var exists;
+ var stat = this.statCache[abs];
+ if (stat !== void 0) {
+ if (stat === false)
+ return cb(null, stat);
+ else {
+ var type = stat.isDirectory() ? "DIR" : "FILE";
+ if (needDir && type === "FILE")
+ return cb();
+ else
+ return cb(null, type, stat);
+ }
+ }
+ var self = this;
+ var statcb = inflight("stat\0" + abs, lstatcb_);
+ if (statcb)
+ fs4.lstat(abs, statcb);
+ function lstatcb_(er, lstat) {
+ if (lstat && lstat.isSymbolicLink()) {
+ return fs4.stat(abs, function(er2, stat2) {
+ if (er2)
+ self._stat2(f, abs, null, lstat, cb);
+ else
+ self._stat2(f, abs, er2, stat2, cb);
+ });
+ } else {
+ self._stat2(f, abs, er, lstat, cb);
+ }
+ }
+ };
+ Glob2.prototype._stat2 = function(f, abs, er, stat, cb) {
+ if (er && (er.code === "ENOENT" || er.code === "ENOTDIR")) {
+ this.statCache[abs] = false;
+ return cb();
+ }
+ var needDir = f.slice(-1) === "/";
+ this.statCache[abs] = stat;
+ if (abs.slice(-1) === "/" && stat && !stat.isDirectory())
+ return cb(null, false, stat);
+ var c = true;
+ if (stat)
+ c = stat.isDirectory() ? "DIR" : "FILE";
+ this.cache[abs] = this.cache[abs] || c;
+ if (needDir && c === "FILE")
+ return cb();
+ return cb(null, c, stat);
+ };
+ }
+});
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/index.ts
+__export(exports, {
+ ExitCode: () => ExitCode,
+ Parameter: () => Parameter,
+ Target: () => Target,
+ chalk: () => chalk4,
+ chdir: () => chdir,
+ createParameter: () => createParameter,
+ createTarget: () => createTarget,
+ exec: () => exec,
+ glob: () => glob,
+ logger: () => logger,
+ rm: () => rm,
+ runner: () => runner,
+ setup: () => setup,
+ sleep: () => sleep
+});
+var import_chalk4 = __toModule(require_source());
+var import_module = __toModule(require("module"));
+
+// pnp:/Users/style/Documents/Projects/juke-build/package.json
+var version = "0.8.1";
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/chdir.ts
+var import_fs = __toModule(require("fs"));
+var import_path = __toModule(require("path"));
+var import_url = __toModule(require("url"));
+var chdir = (directory, relativeTo) => {
+ if (relativeTo) {
+ if (relativeTo.startsWith("file://")) {
+ relativeTo = import_url.default.fileURLToPath(relativeTo);
+ }
+ try {
+ const stat = import_fs.default.statSync(relativeTo);
+ if (!stat.isDirectory()) {
+ relativeTo = import_path.default.dirname(relativeTo);
+ }
+ } catch {
+ relativeTo = import_path.default.dirname(relativeTo);
+ }
+ directory = import_path.default.resolve(relativeTo, directory);
+ }
+ process.chdir(directory);
+};
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/exec.ts
+var import_chalk = __toModule(require_source());
+var import_child_process = __toModule(require("child_process"));
+var import_fs2 = __toModule(require("fs"));
+var import_path2 = __toModule(require("path"));
+var children = new Set();
+var killChildren = () => {
+ for (const child of children) {
+ child.kill("SIGTERM");
+ children.delete(child);
+ console.log("killed child process");
+ }
+};
+var trap = (signals, handler) => {
+ let readline;
+ if (process.platform === "win32") {
+ readline = require("readline").createInterface({
+ input: process.stdin,
+ output: process.stdout
+ });
+ }
+ for (const signal of signals) {
+ const handleSignal = () => handler(signal);
+ if (signal === "EXIT") {
+ process.on("exit", handleSignal);
+ continue;
+ }
+ if (readline) {
+ readline.on("SIG" + signal, handleSignal);
+ }
+ process.on("SIG" + signal, handleSignal);
+ }
+};
+var ExitCode = class extends Error {
+ constructor(code, signal) {
+ super("Process exited with code: " + code);
+ this.code = null;
+ this.signal = null;
+ this.code = code;
+ this.signal = signal || null;
+ }
+};
+var exec = (executable, args = [], options = {}) => {
+ const _a = options, {
+ silent = false,
+ throw: canThrow = true
+ } = _a, spawnOptions = __objRest(_a, [
+ "silent",
+ "throw"
+ ]);
+ return new Promise((resolve, reject) => {
+ if (import_fs2.default.existsSync(executable)) {
+ executable = (0, import_path2.resolve)(executable);
+ }
+ if (process.env.JUKE_DEBUG) {
+ console.log(import_chalk.default.grey("$", executable, ...args));
+ }
+ const child = (0, import_child_process.spawn)(executable, args, spawnOptions);
+ children.add(child);
+ let stdout = "";
+ let stderr = "";
+ let combined = "";
+ child.stdout.on("data", (data) => {
+ if (!silent) {
+ process.stdout.write(data);
+ }
+ stdout += data;
+ combined += data;
+ });
+ child.stderr.on("data", (data) => {
+ if (!silent) {
+ process.stderr.write(data);
+ }
+ stderr += data;
+ combined += data;
+ });
+ child.on("error", (err) => reject(err));
+ child.on("exit", (code, signal) => {
+ children.delete(child);
+ if (code !== 0 && canThrow) {
+ const error = new ExitCode(code);
+ error.code = code;
+ error.signal = signal;
+ reject(error);
+ return;
+ }
+ resolve({
+ code,
+ signal,
+ stdout,
+ stderr,
+ combined
+ });
+ });
+ });
+};
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/logger.ts
+var import_chalk2 = __toModule(require_source());
+var logger = {
+ log: (...args) => {
+ console.log(...args);
+ },
+ error: (...args) => {
+ console.log(import_chalk2.default.bold(import_chalk2.default.redBright("=>"), import_chalk2.default.whiteBright(...args)));
+ },
+ action: (...args) => {
+ console.log(import_chalk2.default.bold(import_chalk2.default.greenBright("=>"), import_chalk2.default.whiteBright(...args)));
+ },
+ warn: (...args) => {
+ console.log(import_chalk2.default.bold(import_chalk2.default.yellowBright("=>"), import_chalk2.default.whiteBright(...args)));
+ },
+ info: (...args) => {
+ console.log(import_chalk2.default.bold(import_chalk2.default.blueBright("::"), import_chalk2.default.whiteBright(...args)));
+ },
+ debug: (...args) => {
+ if (process.env.JUKE_DEBUG) {
+ console.log(import_chalk2.default.gray(...args));
+ }
+ }
+};
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/string.ts
+var import_stringcase = __toModule(require_lib());
+var toKebabCase = (str) => (0, import_stringcase.spinalcase)(str);
+var toCamelCase = (str) => (0, import_stringcase.camelcase)(str);
+var toConstCase = (str) => (0, import_stringcase.constcase)(str);
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/parameter.ts
+var Parameter = class {
+ constructor(config) {
+ this.type = config.type;
+ this.name = config.name;
+ this.alias = config.alias;
+ }
+ isString() {
+ return this.type === "string" || this.type === "string[]";
+ }
+ isNumber() {
+ return this.type === "number" || this.type === "number[]";
+ }
+ isBoolean() {
+ return this.type === "boolean" || this.type === "boolean[]";
+ }
+ isArray() {
+ return this.type.endsWith("[]");
+ }
+ toKebabCase() {
+ if (!this.name)
+ return;
+ return toKebabCase(this.name);
+ }
+ toConstCase() {
+ if (!this.name)
+ return;
+ return toConstCase(this.name);
+ }
+ toCamelCase() {
+ if (!this.name)
+ return;
+ return toCamelCase(this.name);
+ }
+};
+var createParameter = (config) => new Parameter(config);
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/runner.ts
+var import_chalk3 = __toModule(require_source());
+var import_events = __toModule(require("events"));
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/argparse.ts
+var stringToBoolean = (str) => str !== void 0 && str !== null && str !== "false" && str !== "0" && str !== "null";
+var prepareArgs = (args, singleTarget = false) => {
+ let inGlobalContext = true;
+ const globalFlags = [];
+ const taskArgs = [];
+ let currentTaskArgs;
+ while (args.length !== 0) {
+ const arg = args.shift();
+ if (!arg) {
+ continue;
+ }
+ if (arg === "--") {
+ inGlobalContext = false;
+ continue;
+ }
+ if (arg.startsWith("-")) {
+ if (inGlobalContext) {
+ globalFlags.push(arg);
+ } else if (currentTaskArgs) {
+ currentTaskArgs.push(arg);
+ }
+ continue;
+ }
+ inGlobalContext = false;
+ if (singleTarget) {
+ if (!currentTaskArgs) {
+ currentTaskArgs = [arg];
+ } else {
+ currentTaskArgs.push(arg);
+ }
+ continue;
+ }
+ if (currentTaskArgs) {
+ taskArgs.push(currentTaskArgs);
+ }
+ currentTaskArgs = [arg];
+ }
+ if (currentTaskArgs) {
+ taskArgs.push(currentTaskArgs);
+ }
+ return { globalFlags, taskArgs };
+};
+var parseArgs = (args, parameters) => {
+ args = [...args];
+ const parameterMap = new Map();
+ const pushValue = (key, value) => {
+ const values = parameterMap.get(key);
+ if (!values) {
+ parameterMap.set(key, [value]);
+ return;
+ }
+ values.push(value);
+ };
+ let currentSet = [];
+ let currentSetType;
+ while (true) {
+ if (currentSet.length === 0) {
+ const arg2 = args.shift();
+ if (!arg2) {
+ break;
+ }
+ if (arg2.startsWith("--")) {
+ currentSet = [arg2.substr(2)];
+ currentSetType = "long";
+ } else if (arg2.startsWith("-")) {
+ currentSet = Array.from(arg2);
+ currentSetType = "short";
+ } else {
+ currentSet = [];
+ currentSetType = void 0;
+ }
+ }
+ const arg = currentSet.shift();
+ if (currentSetType === "short") {
+ const parameter = parameters.find((p) => p.alias === arg);
+ if (!parameter) {
+ continue;
+ }
+ if (parameter.isBoolean()) {
+ pushValue(parameter, true);
+ continue;
+ }
+ if (currentSet.length === 0) {
+ continue;
+ }
+ const string = currentSet.join("");
+ currentSet = [];
+ if (parameter.isNumber()) {
+ pushValue(parameter, parseFloat(string));
+ continue;
+ }
+ pushValue(parameter, string);
+ continue;
+ }
+ if (currentSetType === "long") {
+ const equalsIndex = arg.indexOf("=");
+ let name = arg;
+ let value = null;
+ if (equalsIndex >= 0) {
+ name = arg.substr(0, equalsIndex);
+ value = arg.substr(equalsIndex + 1);
+ if (value === "") {
+ value = null;
+ }
+ }
+ const parameter = parameters.find((p) => p.name === name || p.toKebabCase() === name || p.toCamelCase() === name);
+ if (!parameter) {
+ continue;
+ }
+ if (parameter.isBoolean()) {
+ const noEqualsSign = equalsIndex < 0;
+ pushValue(parameter, noEqualsSign || stringToBoolean(value));
+ continue;
+ }
+ if (value === null) {
+ continue;
+ }
+ if (parameter.isNumber()) {
+ pushValue(parameter, parseFloat(value));
+ continue;
+ }
+ pushValue(parameter, value);
+ continue;
+ }
+ }
+ for (const [key, value] of Object.entries(process.env)) {
+ const parameter = parameters.find((p) => p.name === key || p.toConstCase() === key);
+ if (!parameter || parameterMap.has(parameter)) {
+ continue;
+ }
+ let values = [];
+ if (value !== void 0) {
+ if (parameter.isArray()) {
+ values = value.split(",");
+ } else {
+ values = [value];
+ }
+ }
+ for (const value2 of values) {
+ if (parameter.isBoolean()) {
+ pushValue(parameter, stringToBoolean(value2));
+ continue;
+ }
+ if (value2 === "") {
+ continue;
+ }
+ if (parameter.isNumber()) {
+ pushValue(parameter, parseFloat(value2));
+ continue;
+ }
+ pushValue(parameter, value2);
+ continue;
+ }
+ }
+ return parameterMap;
+};
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/fs.ts
+var import_fs3 = __toModule(require("fs"));
+var import_glob = __toModule(require_glob());
+var File = class {
+ constructor(path2) {
+ this.path = path2;
+ }
+ get stat() {
+ if (this._stat === void 0) {
+ try {
+ this._stat = import_fs3.default.statSync(this.path);
+ } catch {
+ this._stat = null;
+ }
+ }
+ return this._stat;
+ }
+ exists() {
+ return this.stat !== null;
+ }
+ get mtime() {
+ return this.stat && this.stat.mtime;
+ }
+ touch() {
+ const time = new Date();
+ try {
+ import_fs3.default.utimesSync(this.path, time, time);
+ } catch (err) {
+ import_fs3.default.closeSync(import_fs3.default.openSync(this.path, "w"));
+ }
+ }
+};
+var Glob = class {
+ constructor(path2) {
+ this.path = path2;
+ this.path = path2;
+ }
+ toFiles() {
+ const paths = import_glob.glob.sync(this.path, {
+ strict: false,
+ silent: true
+ });
+ return paths.map((path2) => new File(path2)).filter((file) => file.exists());
+ }
+};
+var compareFiles = (sources, targets) => {
+ let bestSource = null;
+ let bestTarget = null;
+ for (const file of sources) {
+ if (!bestSource || file.mtime > bestSource.mtime) {
+ bestSource = file;
+ }
+ }
+ for (const file of targets) {
+ if (!file.exists()) {
+ return `target '${file.path}' is missing`;
+ }
+ if (!bestTarget || file.mtime < bestTarget.mtime) {
+ bestTarget = file;
+ }
+ }
+ if (!bestSource) {
+ if (bestTarget) {
+ return false;
+ }
+ return "no known sources or targets";
+ }
+ if (!bestTarget) {
+ return "no targets were specified";
+ }
+ if (bestSource.mtime > bestTarget.mtime) {
+ return `source '${bestSource.path}' is newer than target '${bestTarget.path}'`;
+ }
+ return false;
+};
+var glob = (globPath) => {
+ const unsafePaths = import_glob.glob.sync(globPath, {
+ strict: false,
+ silent: true
+ });
+ const safePaths = [];
+ for (let path2 of unsafePaths) {
+ try {
+ import_fs3.default.lstatSync(path2);
+ safePaths.push(path2);
+ } catch {
+ }
+ }
+ return safePaths;
+};
+var rm = (path2, options = {}) => {
+ for (const p of glob(path2)) {
+ try {
+ if (options.recursive && import_fs3.default.rmSync) {
+ import_fs3.default.rmSync(p, options);
+ } else if (options.recursive) {
+ import_fs3.default.rmdirSync(p, { recursive: true });
+ } else {
+ import_fs3.default.unlinkSync(p);
+ }
+ } catch (err) {
+ if (!options.force) {
+ throw err;
+ }
+ }
+ }
+};
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/runner.ts
+var runner = new class Runner {
+ constructor() {
+ this.config = {};
+ this.targets = [];
+ this.parameters = [];
+ this.workers = [];
+ }
+ configure(config) {
+ this.config = config;
+ this.targets = config.targets || [];
+ this.parameters = config.parameters || [];
+ }
+ async start() {
+ const startedAt = Date.now();
+ const { globalFlags, taskArgs } = prepareArgs(process.argv.slice(2), this.config.singleTarget);
+ const globalParameterMap = parseArgs(globalFlags, this.parameters);
+ const targetsToRun = new Map();
+ const showListOfTargets = () => {
+ logger.info("Available targets:");
+ for (const target of this.targets) {
+ logger.log(" - " + import_chalk3.default.cyan(target.name));
+ }
+ logger.info("Available parameters:");
+ for (const parameter of this.parameters) {
+ logger.log(" --" + parameter.name + (parameter.alias ? `, -${parameter.alias}` : "") + ` (type: ${parameter.type})`);
+ }
+ };
+ if (globalFlags.includes("-h") || globalFlags.includes("--help")) {
+ showListOfTargets();
+ process.exit(1);
+ }
+ for (const [taskName, ...args] of taskArgs) {
+ const target = this.targets.find((t) => t.name === taskName);
+ if (!target) {
+ const nameStr = import_chalk3.default.cyan(taskName);
+ logger.error(`Task '${nameStr}' was not found.`);
+ showListOfTargets();
+ process.exit(1);
+ }
+ targetsToRun.set(target, { args });
+ }
+ if (targetsToRun.size === 0) {
+ if (!this.config.default) {
+ logger.error(`No task was provided in arguments.`);
+ showListOfTargets();
+ process.exit(1);
+ }
+ targetsToRun.set(this.config.default, {
+ args: []
+ });
+ }
+ let toVisit = Array.from(targetsToRun.entries());
+ while (true) {
+ const node = toVisit.shift();
+ if (!node) {
+ break;
+ }
+ const [target, meta] = node;
+ if (!meta.context) {
+ const localParameterMap = parseArgs(meta.args, target.parameters);
+ meta.context = {
+ get: (parameter) => {
+ let value = localParameterMap.get(parameter);
+ if (value === void 0) {
+ value = globalParameterMap.get(parameter);
+ }
+ if (parameter.isArray()) {
+ return value || [];
+ } else {
+ const returnValue = value && value[0];
+ return returnValue !== void 0 ? returnValue : null;
+ }
+ },
+ args: meta.args
+ };
+ }
+ if (!meta.dependsOn) {
+ const optionalDependsOn = (typeof target.dependsOn === "function" ? await target.dependsOn(meta.context) : target.dependsOn) || [];
+ meta.dependsOn = optionalDependsOn.filter((dep) => typeof dep === "object" && dep !== null);
+ }
+ for (const dependency of meta.dependsOn) {
+ if (!targetsToRun.has(dependency)) {
+ const depMeta = { args: meta.args };
+ targetsToRun.set(dependency, depMeta);
+ toVisit.push([dependency, depMeta]);
+ } else {
+ logger.debug("Dropped a possible circular dependency", dependency);
+ }
+ }
+ }
+ for (const [target, meta] of targetsToRun.entries()) {
+ const context = meta.context;
+ const dependsOn = meta.dependsOn;
+ const spawnedWorker = new Worker(target, context, dependsOn);
+ this.workers.push(spawnedWorker);
+ spawnedWorker.onFinish(() => {
+ for (const worker of this.workers) {
+ if (worker === spawnedWorker) {
+ continue;
+ }
+ worker.resolveDependency(target);
+ }
+ });
+ spawnedWorker.onFail(() => {
+ for (const worker of this.workers) {
+ if (worker === spawnedWorker) {
+ continue;
+ }
+ worker.rejectDependency(target);
+ }
+ });
+ }
+ const resolutions = await Promise.all(this.workers.map((worker) => new Promise((resolve) => {
+ worker.onFinish(() => resolve(true));
+ worker.onFail(() => resolve(false));
+ worker.start();
+ })));
+ const hasFailedWorkers = resolutions.includes(false);
+ if (!hasFailedWorkers) {
+ const time = (Date.now() - startedAt) / 1e3 + "s";
+ const timeStr = import_chalk3.default.magenta(time);
+ logger.action(`Done in ${timeStr}`);
+ }
+ return Number(hasFailedWorkers);
+ }
+}();
+var Worker = class {
+ constructor(target, context, dependsOn) {
+ this.target = target;
+ this.context = context;
+ this.dependsOn = dependsOn;
+ this.emitter = new import_events.default();
+ this.hasFailed = false;
+ this.dependencies = new Set(dependsOn);
+ this.debugLog("ready");
+ }
+ resolveDependency(target) {
+ var _a;
+ this.dependencies.delete(target);
+ (_a = this.generator) == null ? void 0 : _a.next();
+ }
+ rejectDependency(target) {
+ var _a;
+ this.dependencies.delete(target);
+ this.hasFailed = true;
+ (_a = this.generator) == null ? void 0 : _a.next();
+ }
+ start() {
+ this.generator = this.process();
+ this.generator.next();
+ }
+ onFinish(fn) {
+ this.emitter.once("finish", fn);
+ }
+ onFail(fn) {
+ this.emitter.once("fail", fn);
+ }
+ debugLog(...args) {
+ logger.debug(`${this.target.name}:`, ...args);
+ }
+ async *process() {
+ const nameStr = import_chalk3.default.cyan(this.target.name);
+ this.debugLog("Waiting for dependencies");
+ while (true) {
+ if (this.dependencies.size === 0) {
+ break;
+ }
+ yield;
+ }
+ if (this.hasFailed) {
+ const nameStr2 = import_chalk3.default.cyan(this.target.name);
+ logger.error(`Target '${nameStr2}' failed`);
+ this.emitter.emit("fail");
+ return;
+ }
+ if (this.target.onlyWhen) {
+ const result = await this.target.onlyWhen(this.context);
+ if (!result) {
+ logger.info(`Skipping '${nameStr}' (condition unmet)`);
+ this.emitter.emit("finish");
+ return;
+ }
+ this.debugLog("Needs rebuild based on onlyWhen condition");
+ }
+ this.debugLog("Comparing inputs and outputs");
+ const fileMapper = async (fileIo) => {
+ const optionalPaths = (typeof fileIo === "function" ? await fileIo(this.context) : fileIo) || [];
+ const paths = optionalPaths.filter((path2) => typeof path2 === "string");
+ return paths.flatMap((path2) => path2.includes("*") ? new Glob(path2).toFiles() : new File(path2));
+ };
+ const inputs = await fileMapper(this.target.inputs);
+ const outputs = await fileMapper(this.target.outputs);
+ if (inputs.length > 0) {
+ const needsRebuild = compareFiles(inputs, outputs);
+ if (!needsRebuild) {
+ logger.info(`Skipping '${nameStr}' (up to date)`);
+ this.emitter.emit("finish");
+ return;
+ } else {
+ this.debugLog("Needs rebuild, reason:", needsRebuild);
+ }
+ } else {
+ this.debugLog("Nothing to compare");
+ }
+ if (this.hasFailed) {
+ const nameStr2 = import_chalk3.default.cyan(this.target.name);
+ logger.error(`Target '${nameStr2}' failed (at file comparison stage)`);
+ this.emitter.emit("fail");
+ return;
+ }
+ if (this.target.executes) {
+ logger.action(`Starting '${nameStr}'`);
+ const startedAt = Date.now();
+ try {
+ await this.target.executes(this.context);
+ } catch (err) {
+ const time2 = (Date.now() - startedAt) / 1e3 + "s";
+ const timeStr2 = import_chalk3.default.magenta(time2);
+ if (err instanceof ExitCode) {
+ const codeStr = import_chalk3.default.red(err.code);
+ logger.error(`Target '${nameStr}' failed in ${timeStr2}, exit code: ${codeStr}`);
+ } else {
+ logger.error(`Target '${nameStr}' failed in ${timeStr2}, unhandled exception:`);
+ console.error(err);
+ }
+ this.emitter.emit("fail");
+ return;
+ }
+ const time = (Date.now() - startedAt) / 1e3 + "s";
+ const timeStr = import_chalk3.default.magenta(time);
+ logger.action(`Finished '${nameStr}' in ${timeStr}`);
+ }
+ if (outputs.length > 0) {
+ for (const file of outputs) {
+ file.touch();
+ }
+ }
+ this.emitter.emit("finish");
+ }
+};
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/target.ts
+var Target = class {
+ constructor(target) {
+ this.name = target.name;
+ this.dependsOn = target.dependsOn || [];
+ this.executes = target.executes;
+ this.inputs = target.inputs || [];
+ this.outputs = target.outputs || [];
+ this.parameters = target.parameters || [];
+ this.onlyWhen = target.onlyWhen;
+ }
+};
+var createTarget = (config) => new Target(config);
+
+// pnp:/Users/style/Documents/Projects/juke-build/src/index.ts
+var chalk4 = import_chalk4.default;
+var lastExitCode = null;
+var setup = async (config) => {
+ logger.info(`Juke Build version ${version}`);
+ if (!config.file) {
+ logger.error(`Field 'file' is required in Juke.setup()`);
+ process.exit(1);
+ }
+ let buildModule = await import(config.file);
+ const isCommonJs = Boolean((0, import_module.createRequire)(config.file).cache[config.file]);
+ if (isCommonJs) {
+ buildModule = buildModule.default;
+ }
+ const targets = [];
+ const parameters = [];
+ for (const name of Object.keys(buildModule)) {
+ if (name === "default") {
+ continue;
+ }
+ const obj = buildModule[name];
+ if (obj instanceof Target) {
+ if (!obj.name) {
+ obj.name = name !== "Target" ? toKebabCase(name.replace(/Target$/, "")) : "target";
+ }
+ targets.push(obj);
+ continue;
+ }
+ if (obj instanceof Parameter) {
+ if (!obj.name) {
+ obj.name = name !== "Parameter" ? toKebabCase(name.replace(/Parameter$/, "")) : "parameter";
+ }
+ parameters.push(obj);
+ continue;
+ }
+ }
+ const DefaultTarget = buildModule.default || buildModule.DefaultTarget || buildModule.Default;
+ if (DefaultTarget && !(DefaultTarget instanceof Target)) {
+ logger.error(`Default export is not a valid 'Target' object.`);
+ process.exit(1);
+ }
+ runner.configure({
+ parameters,
+ targets,
+ default: DefaultTarget,
+ singleTarget: config.singleTarget
+ });
+ return runner.start().then((code) => {
+ lastExitCode = code;
+ return code;
+ });
+};
+var sleep = (time) => new Promise((resolve) => setTimeout(resolve, time));
+trap(["EXIT", "BREAK", "HUP", "INT", "TERM"], (signal) => {
+ if (signal !== "EXIT") {
+ console.log("Received", signal);
+ }
+ killChildren();
+ if (signal !== "EXIT") {
+ process.exit(1);
+ } else if (lastExitCode !== null) {
+ process.exit(lastExitCode);
+ }
+});
+var exceptionHandler = (err) => {
+ console.log(err);
+ killChildren();
+ process.exit(1);
+};
+process.on("unhandledRejection", exceptionHandler);
+process.on("uncaughtException", exceptionHandler);
+// Annotate the CommonJS export names for ESM import in node:
+0 && (module.exports = {
+ ExitCode,
+ Parameter,
+ Target,
+ chalk,
+ chdir,
+ createParameter,
+ createTarget,
+ exec,
+ glob,
+ logger,
+ rm,
+ runner,
+ setup,
+ sleep
+});
diff --git a/tools/build/juke/package.json b/tools/build/juke/package.json
new file mode 100644
index 0000000000..0fef86e339
--- /dev/null
+++ b/tools/build/juke/package.json
@@ -0,0 +1,4 @@
+{
+ "private": true,
+ "type": "commonjs"
+}
diff --git a/tools/build/lib/byond.js b/tools/build/lib/byond.js
new file mode 100644
index 0000000000..952b60c4e9
--- /dev/null
+++ b/tools/build/lib/byond.js
@@ -0,0 +1,115 @@
+import fs from 'fs';
+import path from 'path';
+import Juke from '../juke/index.js';
+import { regQuery } from './winreg.js';
+
+/**
+ * Cached path to DM compiler
+ */
+let dmPath;
+
+const getDmPath = async () => {
+ if (dmPath) {
+ return dmPath;
+ }
+ dmPath = await (async () => {
+ // Search in array of paths
+ const paths = [
+ ...((process.env.DM_EXE && process.env.DM_EXE.split(',')) || []),
+ 'C:\\Program Files\\BYOND\\bin\\dm.exe',
+ 'C:\\Program Files (x86)\\BYOND\\bin\\dm.exe',
+ ['reg', 'HKLM\\Software\\Dantom\\BYOND', 'installpath'],
+ ['reg', 'HKLM\\SOFTWARE\\WOW6432Node\\Dantom\\BYOND', 'installpath'],
+ ];
+ const isFile = path => {
+ try {
+ return fs.statSync(path).isFile();
+ }
+ catch (err) {
+ return false;
+ }
+ };
+ for (let path of paths) {
+ // Resolve a registry key
+ if (Array.isArray(path)) {
+ const [type, ...args] = path;
+ path = await regQuery(...args);
+ }
+ if (!path) {
+ continue;
+ }
+ // Check if path exists
+ if (isFile(path)) {
+ return path;
+ }
+ if (isFile(path + '/dm.exe')) {
+ return path + '/dm.exe';
+ }
+ if (isFile(path + '/bin/dm.exe')) {
+ return path + '/bin/dm.exe';
+ }
+ }
+ // Default paths
+ return (
+ process.platform === 'win32' && 'dm.exe'
+ || 'DreamMaker'
+ );
+ })();
+ return dmPath;
+};
+
+/**
+ * @param {string} dmeFile
+ * @param {{ defines?: string[] }} options
+ */
+export const DreamMaker = async (dmeFile, options = {}) => {
+ const dmPath = await getDmPath();
+ // Get project basename
+ const dmeBaseName = dmeFile.replace(/\.dme$/, '');
+ // Make sure output files are writable
+ const testOutputFile = (name) => {
+ try {
+ fs.closeSync(fs.openSync(name, 'r+'));
+ }
+ catch (err) {
+ if (err && err.code === 'ENOENT') {
+ return;
+ }
+ if (err && err.code === 'EBUSY') {
+ Juke.logger.error(`File '${name}' is locked by the DreamDaemon process.`);
+ Juke.logger.error(`Stop the currently running server and try again.`);
+ throw new Juke.ExitCode(1);
+ }
+ throw err;
+ }
+ };
+ testOutputFile(`${dmeBaseName}.dmb`);
+ testOutputFile(`${dmeBaseName}.rsc`);
+ // Compile
+ const { defines } = options;
+ if (defines && defines.length > 0) {
+ const injectedContent = defines
+ .map(x => `#define ${x}\n`)
+ .join('');
+ fs.writeFileSync(`${dmeBaseName}.m.dme`, injectedContent);
+ const dmeContent = fs.readFileSync(`${dmeBaseName}.dme`);
+ fs.appendFileSync(`${dmeBaseName}.m.dme`, dmeContent);
+ await Juke.exec(dmPath, [`${dmeBaseName}.m.dme`]);
+ fs.writeFileSync(`${dmeBaseName}.dmb`, fs.readFileSync(`${dmeBaseName}.m.dmb`));
+ fs.writeFileSync(`${dmeBaseName}.rsc`, fs.readFileSync(`${dmeBaseName}.m.rsc`));
+ fs.unlinkSync(`${dmeBaseName}.m.dmb`);
+ fs.unlinkSync(`${dmeBaseName}.m.rsc`);
+ fs.unlinkSync(`${dmeBaseName}.m.dme`);
+ }
+ else {
+ await Juke.exec(dmPath, [dmeFile]);
+ }
+};
+
+export const DreamDaemon = async (dmbFile, ...args) => {
+ const dmPath = await getDmPath();
+ const baseDir = path.dirname(dmPath);
+ const ddExeName = process.platform === 'win32' ? 'dd.exe' : 'DreamDaemon';
+ const ddExePath = baseDir === '.' ? ddExeName : path.join(baseDir, ddExeName);
+ return Juke.exec(ddExePath, [dmbFile, ...args]);
+};
diff --git a/tools/build/cbt/winreg.js b/tools/build/lib/winreg.js
similarity index 81%
rename from tools/build/cbt/winreg.js
rename to tools/build/lib/winreg.js
index a19aa66f48..0916ea3a31 100644
--- a/tools/build/cbt/winreg.js
+++ b/tools/build/lib/winreg.js
@@ -4,14 +4,14 @@
* Adapted from `tgui/packages/tgui-dev-server/winreg.js`.
*
* @file
- * @copyright 2020 Aleksej Komarov
+ * @copyright 2021 Aleksej Komarov
* @license MIT
*/
-const { exec } = require('child_process');
-const { promisify } = require('util');
+import { exec } from 'child_process';
+import { promisify } from 'util';
-const regQuery = async (path, key) => {
+export const regQuery = async (path, key) => {
if (process.platform !== 'win32') {
return null;
}
@@ -40,7 +40,3 @@ const regQuery = async (path, key) => {
return null;
}
};
-
-module.exports = {
- regQuery,
-};
diff --git a/tools/build/lib/yarn.js b/tools/build/lib/yarn.js
new file mode 100644
index 0000000000..8b93f4cfc9
--- /dev/null
+++ b/tools/build/lib/yarn.js
@@ -0,0 +1,13 @@
+import Juke from '../juke/index.js';
+
+let yarnPath;
+
+export const yarn = (...args) => {
+ if (!yarnPath) {
+ yarnPath = Juke.glob('./tgui/.yarn/releases/*.cjs')[0]
+ .replace('/tgui/', '/');
+ }
+ return Juke.exec('node', [yarnPath, ...args], {
+ cwd: './tgui',
+ });
+};
diff --git a/tools/build/package.json b/tools/build/package.json
new file mode 100644
index 0000000000..e986b24bba
--- /dev/null
+++ b/tools/build/package.json
@@ -0,0 +1,4 @@
+{
+ "private": true,
+ "type": "module"
+}
From c25dc84da073a75dd7d78afb85e53808680ae8e5 Mon Sep 17 00:00:00 2001
From: LetterN <24603524+LetterN@users.noreply.github.com>
Date: Wed, 8 Sep 2021 09:25:38 +0800
Subject: [PATCH 03/11] what the cat doing with the yarn dependencies??
---
.github/workflows/ci_suite.yml | 62 ++++--
.github/workflows/generate_documentation.yml | 4 +-
code/__DEFINES/qdel.dm | 42 ++--
code/__DEFINES/time.dm | 6 +
code/_compile_options.dm | 67 ++++--
.../configuration/entries/general.dm | 9 +
code/controllers/subsystem/garbage.dm | 197 +++++++++---------
config/entries/general.txt | 6 +
dependencies.sh | 18 +-
9 files changed, 243 insertions(+), 168 deletions(-)
diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml
index f36055dab0..34c1ec1b0e 100644
--- a/.github/workflows/ci_suite.yml
+++ b/.github/workflows/ci_suite.yml
@@ -13,11 +13,20 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- - name: Setup cache
+ - name: Restore SpacemanDMM cache
uses: actions/cache@v2
with:
- path: $HOME/SpacemanDMM
- key: ${{ runner.os }}-spacemandmm
+ path: ~/SpacemanDMM
+ key: ${{ runner.os }}-spacemandmm-${{ secrets.CACHE_PURGE_KEY }}
+ - name: Restore Yarn cache
+ uses: actions/cache@v2
+ with:
+ path: tgui/.yarn/cache
+ key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-build-${{ secrets.CACHE_PURGE_KEY }}-
+ ${{ runner.os }}-build-
+ ${{ runner.os }}-
- name: Install Tools
run: |
pip3 install setuptools
@@ -28,11 +37,10 @@ jobs:
run: |
bash tools/ci/check_filedirs.sh tgstation.dme
bash tools/ci/check_changelogs.sh
+ bash tools/ci/check_grep.sh
find . -name "*.php" -print0 | xargs -0 -n1 php -l
find . -name "*.json" -not -path "*/node_modules/*" -print0 | xargs -0 python3 ./tools/json_verifier.py
- tgui/bin/tgui --lint
- tgui/bin/tgui --test
- bash tools/ci/check_grep.sh
+ tools/build/build --ci lint
tools/bootstrap/python -m dmi.test
tools/bootstrap/python -m mapmerge2.dmm_test
~/dreamchecker > ${GITHUB_WORKSPACE}/output-annotations.txt 2>&1
@@ -48,19 +56,16 @@ jobs:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
- - name: Setup cache
+ - name: Restore BYOND cache
uses: actions/cache@v2
with:
- path: $HOME/BYOND
- key: ${{ runner.os }}-byond
+ path: ~/BYOND
+ key: ${{ runner.os }}-byond-${{ secrets.CACHE_PURGE_KEY }}
- name: Compile All Maps
run: |
bash tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
- python3 tools/ci/template_dm_generator.py
- tools/build/build
- env:
- CBT_BUILD_MODE : ALL_MAPS
+ tools/build/build --ci dm -DCIBUILDING -DCITESTING -DALL_MAPS
run_all_tests:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
@@ -76,11 +81,20 @@ jobs:
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v2
- - name: Setup cache
+ - name: Restore BYOND cache
uses: actions/cache@v2
with:
- path: $HOME/BYOND
- key: ${{ runner.os }}-byond
+ path: ~/BYOND
+ key: ${{ runner.os }}-byond-${{ secrets.CACHE_PURGE_KEY }}
+ - name: Restore Yarn cache
+ uses: actions/cache@v2
+ with:
+ path: tgui/.yarn/cache
+ key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-build-${{ secrets.CACHE_PURGE_KEY }}-
+ ${{ runner.os }}-build-
+ ${{ runner.os }}-
- name: Setup database
run: |
sudo systemctl start mysql
@@ -88,7 +102,7 @@ jobs:
mysql -u root -proot tg_ci < SQL/tgstation_schema.sql
mysql -u root -proot -e 'CREATE DATABASE tg_ci_prefixed;'
mysql -u root -proot tg_ci_prefixed < SQL/tgstation_schema_prefixed.sql
- - name: Install rust dependencies
+ - name: Install rust-g
run: |
sudo dpkg --add-architecture i386
sudo apt update || true
@@ -96,15 +110,14 @@ jobs:
bash tools/ci/install_rust_g.sh
- name: Install auxmos
run: |
+ sudo apt update || true
bash tools/ci/install_auxmos.sh
- name: Compile and run tests
run: |
bash tools/ci/install_byond.sh
source $HOME/BYOND/byond/bin/byondsetup
- tools/build/build -DCIBUILDING
+ tools/build/build --ci -DCIBUILDING
bash tools/ci/run_server.sh
- env:
- CBT_BUILD_MODE: TEST_RUN
test_windows:
if: "!contains(github.event.head_commit.message, '[ci skip]')"
@@ -112,6 +125,15 @@ jobs:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
+ - name: Restore Yarn cache
+ uses: actions/cache@v2
+ with:
+ path: tgui/.yarn/cache
+ key: ${{ runner.os }}-yarn-${{ secrets.CACHE_PURGE_KEY }}-${{ hashFiles('tgui/yarn.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-build-${{ secrets.CACHE_PURGE_KEY }}-
+ ${{ runner.os }}-build-
+ ${{ runner.os }}-
- name: Compile
run: pwsh tools/ci/build.ps1
env:
diff --git a/.github/workflows/generate_documentation.yml b/.github/workflows/generate_documentation.yml
index 0fa3f315be..265e179ff0 100644
--- a/.github/workflows/generate_documentation.yml
+++ b/.github/workflows/generate_documentation.yml
@@ -12,8 +12,8 @@ jobs:
- name: Setup cache
uses: actions/cache@v2
with:
- path: $HOME/SpacemanDMM
- key: ${{ runner.os }}-spacemandmm
+ path: ~/SpacemanDMM
+ key: ${{ runner.os }}-spacemandmm-${{ secrets.CACHE_PURGE_KEY }}
- name: Install SpacemanDMM
run: bash tools/ci/install_spaceman_dmm.sh dmdoc
- name: Generate documentation
diff --git a/code/__DEFINES/qdel.dm b/code/__DEFINES/qdel.dm
index 63259774fa..32e0025ab2 100644
--- a/code/__DEFINES/qdel.dm
+++ b/code/__DEFINES/qdel.dm
@@ -1,30 +1,44 @@
-//defines that give qdel hints. these can be given as a return in destory() or by calling
+//! Defines that give qdel hints.
+//!
+//! These can be given as a return in [/atom/proc/Destroy] or by calling [/proc/qdel].
+
+/// `qdel` should queue the object for deletion.
+#define QDEL_HINT_QUEUE 0
+/// `qdel` should let the object live after calling [/atom/proc/Destroy].
+#define QDEL_HINT_LETMELIVE 1
+/// Functionally the same as the above. `qdel` should assume the object will gc on its own, and not check it.
+#define QDEL_HINT_IWILLGC 2
+/// Qdel should assume this object won't GC, and queue a hard delete using a hard reference.
+#define QDEL_HINT_HARDDEL 3
+// Qdel should assume this object won't gc, and hard delete it posthaste.
+#define QDEL_HINT_HARDDEL_NOW 4
-#define QDEL_HINT_QUEUE 0 //qdel should queue the object for deletion.
-#define QDEL_HINT_LETMELIVE 1 //qdel should let the object live after calling destory.
-#define QDEL_HINT_IWILLGC 2 //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
-#define QDEL_HINT_HARDDEL 3 //qdel should assume this object won't gc, and queue a hard delete using a hard reference.
-#define QDEL_HINT_HARDDEL_NOW 4 //qdel should assume this object won't gc, and hard del it post haste.
-
-#ifdef LEGACY_REFERENCE_TRACKING
-/** If LEGACY_REFERENCE_TRACKING is enabled, qdel will call this object's find_references() verb.
- *
- * Functionally identical to QDEL_HINT_QUEUE if GC_FAILURE_HARD_LOOKUP is not enabled in _compiler_options.dm.
+#ifdef REFERENCE_TRACKING
+/** If REFERENCE_TRACKING is enabled, qdel will call this object's find_references() verb.
+ *
+ * Functionally identical to [QDEL_HINT_QUEUE] if [GC_FAILURE_HARD_LOOKUP] is not enabled in _compiler_options.dm.
*/
-#define QDEL_HINT_FINDREFERENCE 5
-/// Behavior as QDEL_HINT_FINDREFERENCE, but only if the GC fails and a hard delete is forced.
+#define QDEL_HINT_FINDREFERENCE 5
+/// Behavior as [QDEL_HINT_FINDREFERENCE], but only if the GC fails and a hard delete is forced.
#define QDEL_HINT_IFFAIL_FINDREFERENCE 6
#endif
-
#define GC_QUEUE_CHECK 1
#define GC_QUEUE_HARDDELETE 2
#define GC_QUEUE_COUNT 2 //increase this when adding more steps.
+#define QDEL_ITEM_ADMINS_WARNED (1<<0) //! Set when admins are told about lag causing qdels in this type.
+#define QDEL_ITEM_SUSPENDED_FOR_LAG (1<<1) //! Set when a type can no longer be hard deleted on failure because of lag it causes while this happens.
+
+// Defines for the [gc_destroyed][/datum/var/gc_destroyed] var.
#define GC_QUEUED_FOR_QUEUING -1
#define GC_CURRENTLY_BEING_QDELETED -2
+// Defines for the time left for an item to get its reference cleaned
+#define GC_FILTER_QUEUE 5 MINUTES
+#define GC_DEL_QUEUE 10 SECONDS
+
#define QDELING(X) (X.gc_destroyed)
#define QDELETED(X) (!X || QDELING(X))
#define QDESTROYING(X) (!X || X.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
diff --git a/code/__DEFINES/time.dm b/code/__DEFINES/time.dm
index 01990ddc17..252fe0910e 100644
--- a/code/__DEFINES/time.dm
+++ b/code/__DEFINES/time.dm
@@ -49,10 +49,16 @@ When using time2text(), please use "DDD" to find the weekday. Refrain from using
#define TICKS *world.tick_lag
+#define MILLISECONDS * 0.01
+
#define DS2TICKS(DS) ((DS)/world.tick_lag)
#define TICKS2DS(T) ((T) TICKS)
+#define MS2DS(T) ((T) MILLISECONDS)
+
+#define DS2MS(T) ((T) * 100)
+
#define GAMETIMESTAMP(format, wtime) time2text(wtime, format)
#define WORLDTIME2TEXT(format) GAMETIMESTAMP(format, world.time)
#define WORLDTIMEOFDAY2TEXT(format) GAMETIMESTAMP(format, world.timeofday)
diff --git a/code/_compile_options.dm b/code/_compile_options.dm
index 64b4129024..b19b2eba6d 100644
--- a/code/_compile_options.dm
+++ b/code/_compile_options.dm
@@ -1,7 +1,7 @@
-//#define TESTING //By using the testing("message") proc you can create debug-feedback for people with this
+//#define TESTING //By using the testing("message") proc you can create debug-feedback for people with this
//uncommented, but not visible in the release version)
-//#define DATUMVAR_DEBUGGING_MODE //Enables the ability to cache datum vars and retrieve later for debugging which vars changed.
+//#define DATUMVAR_DEBUGGING_MODE //Enables the ability to cache datum vars and retrieve later for debugging which vars changed.
// Comment this out if you are debugging problems that might be obscured by custom error handling in world/Error
#ifdef DEBUG
@@ -11,34 +11,41 @@
#ifdef TESTING
#define DATUMVAR_DEBUGGING_MODE
-/*
-* Enables extools-powered reference tracking system, letting you see what is referencing objects that refuse to hard delete.
-*
-* * Requires TESTING to be defined to work.
-*/
+///Used to find the sources of harddels, quite laggy, don't be surpised if it freezes your client for a good while
//#define REFERENCE_TRACKING
+#ifdef REFERENCE_TRACKING
-///Method of tracking references without using extools. Slower, kept to avoid over-reliance on extools.
-//#define LEGACY_REFERENCE_TRACKING
-#ifdef LEGACY_REFERENCE_TRACKING
+///Should we be logging our findings or not
+#define REFERENCE_TRACKING_LOG
-///Use the legacy reference on things hard deleting by default.
+///Used for doing dry runs of the reference finder, to test for feature completeness
+//#define REFERENCE_TRACKING_DEBUG
+
+///Run a lookup on things hard deleting by default.
//#define GC_FAILURE_HARD_LOOKUP
#ifdef GC_FAILURE_HARD_LOOKUP
#define FIND_REF_NO_CHECK_TICK
#endif //ifdef GC_FAILURE_HARD_LOOKUP
-#endif //ifdef LEGACY_REFERENCE_TRACKING
+#endif //ifdef REFERENCE_TRACKING
-//#define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green
+/*
+* Enables debug messages for every single reaction step. This is 1 message per 0.5s for a SINGLE reaction. Useful for tracking down bugs/asking me for help in the main reaction handiler (equilibrium.dm).
+*
+* * Requires TESTING to be defined to work.
+*/
+//#define REAGENTS_TESTING
+// #define VISUALIZE_ACTIVE_TURFS //Highlights atmos active turfs in green
+// #define TRACK_MAX_SHARE //Allows max share tracking, for use in the atmos debugging ui
#endif //ifdef TESTING
-//#define UNIT_TESTS //Enables unit tests via TEST_RUN_PARAMETER
-#ifndef PRELOAD_RSC //set to:
-#define PRELOAD_RSC 2 // 0 to allow using external resources or on-demand behaviour;
-#endif // 1 to use the default behaviour;
- // 2 for preloading absolutely everything;
+//#define UNIT_TESTS //If this is uncommented, we do a single run though of the game setup and tear down process with unit tests in between
+
+#ifndef PRELOAD_RSC //set to:
+#define PRELOAD_RSC 2 // 0 to allow using external resources or on-demand behaviour;
+#endif // 1 to use the default behaviour;
+ // 2 for preloading absolutely everything;
#ifdef LOWMEMORYMODE
#define FORCE_MAP "_maps/runtimestation.json"
@@ -47,7 +54,7 @@
//Update this whenever you need to take advantage of more recent byond features
#define MIN_COMPILER_VERSION 513
#define MIN_COMPILER_BUILD 1514
-#if DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD
+#if (DM_VERSION < MIN_COMPILER_VERSION || DM_BUILD < MIN_COMPILER_BUILD) && !defined(SPACEMAN_DMM)
//Don't forget to update this part
#error Your version of BYOND is too out-of-date to compile this project. Go to https://secure.byond.com/download and update.
#error You need version 513.1514 or higher
@@ -58,10 +65,6 @@
#warn compiling in TESTING mode. testing() debug messages will be visible.
#endif
-#ifdef GC_FAILURE_HARD_LOOKUP
-#define FIND_REF_NO_CHECK_TICK
-#endif
-
#ifdef CIBUILDING
#define UNIT_TESTS
#endif
@@ -70,6 +73,24 @@
#define TESTING
#endif
+#if defined(UNIT_TESTS)
+//Hard del testing defines
+#define REFERENCE_TRACKING
+#define REFERENCE_TRACKING_DEBUG
+#define FIND_REF_NO_CHECK_TICK
+#endif
+
+#ifdef TGS
+// TGS performs its own build of dm.exe, but includes a prepended TGS define.
+#define CBT
+#endif
+
// A reasonable number of maximum overlays an object needs
// If you think you need more, rethink it
#define MAX_ATOM_OVERLAYS 100
+
+#if !defined(CBT) && !defined(SPACEMAN_DMM)
+#warn Building with Dream Maker is no longer supported and will result in errors.
+#warn In order to build, run BUILD.bat in the root directory.
+#warn Consider switching to VSCode editor instead, where you can press Ctrl+Shift+B to build.
+#endif
diff --git a/code/controllers/configuration/entries/general.dm b/code/controllers/configuration/entries/general.dm
index 8ecd7c0c60..d828457fa7 100644
--- a/code/controllers/configuration/entries/general.dm
+++ b/code/controllers/configuration/entries/general.dm
@@ -333,3 +333,12 @@
config_entry_value = 0.333
min_val = 0
integer = FALSE
+
+/datum/config_entry/number/hard_deletes_overrun_threshold
+ integer = FALSE
+ min_val = 0
+ default = 0.5
+
+/datum/config_entry/number/hard_deletes_overrun_limit
+ default = 0
+ min_val = 0
diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm
index 2d2fac1d13..7f7d301a1d 100644
--- a/code/controllers/subsystem/garbage.dm
+++ b/code/controllers/subsystem/garbage.dm
@@ -29,37 +29,35 @@ SUBSYSTEM_DEF(garbage)
runlevels = RUNLEVELS_DEFAULT | RUNLEVEL_LOBBY
init_order = INIT_ORDER_GARBAGE
- var/list/collection_timeout = list(2 MINUTES, 10 SECONDS) // deciseconds to wait before moving something up in the queue to the next level
+ var/list/collection_timeout = list(GC_FILTER_QUEUE, GC_DEL_QUEUE) // deciseconds to wait before moving something up in the queue to the next level
//Stat tracking
- var/delslasttick = 0 // number of del()'s we've done this tick
- var/gcedlasttick = 0 // number of things that gc'ed last tick
+ var/delslasttick = 0 // number of del()'s we've done this tick
+ var/gcedlasttick = 0 // number of things that gc'ed last tick
var/totaldels = 0
var/totalgcs = 0
- var/highest_del_time = 0
- var/highest_del_tickusage = 0
+ var/highest_del_ms = 0
+ var/highest_del_type_string = ""
var/list/pass_counts
var/list/fail_counts
- var/list/items = list() // Holds our qdel_item statistics datums
+ var/list/items = list() // Holds our qdel_item statistics datums
//Queue
var/list/queues
- #ifdef LEGACY_REFERENCE_TRACKING
+ #ifdef REFERENCE_TRACKING
var/list/reference_find_on_fail = list()
+ #ifdef REFERENCE_TRACKING_DEBUG
+ //Should we save found refs. Used for unit testing
+ var/should_save_refs = FALSE
+ #endif
#endif
/datum/controller/subsystem/garbage/PreInit()
- queues = new(GC_QUEUE_COUNT)
- pass_counts = new(GC_QUEUE_COUNT)
- fail_counts = new(GC_QUEUE_COUNT)
- for(var/i in 1 to GC_QUEUE_COUNT)
- queues[i] = list()
- pass_counts[i] = 0
- fail_counts[i] = 0
+ InitQueues()
/datum/controller/subsystem/garbage/stat_entry(msg)
var/list/counts = list()
@@ -90,13 +88,18 @@ SUBSYSTEM_DEF(garbage)
for(var/path in items)
var/datum/qdel_item/I = items[path]
dellog += "Path: [path]"
+ if (I.qdel_flags & QDEL_ITEM_SUSPENDED_FOR_LAG)
+ dellog += "\tSUSPENDED FOR LAG"
if (I.failures)
dellog += "\tFailures: [I.failures]"
dellog += "\tqdel() Count: [I.qdels]"
dellog += "\tDestroy() Cost: [I.destroy_time]ms"
if (I.hard_deletes)
- dellog += "\tTotal Hard Deletes [I.hard_deletes]"
+ dellog += "\tTotal Hard Deletes: [I.hard_deletes]"
dellog += "\tTime Spent Hard Deleting: [I.hard_delete_time]ms"
+ dellog += "\tHighest Time Spent Hard Deleting: [I.hard_delete_max]ms"
+ if (I.hard_deletes_over_threshold)
+ dellog += "\tHard Deletes Over Threshold: [I.hard_deletes_over_threshold]"
if (I.slept_destroy)
dellog += "\tSleeps: [I.slept_destroy]"
if (I.no_respect_force)
@@ -122,6 +125,15 @@ SUBSYSTEM_DEF(garbage)
+/datum/controller/subsystem/garbage/proc/InitQueues()
+ if (isnull(queues)) // Only init the queues if they don't already exist, prevents overriding of recovered lists
+ queues = new(GC_QUEUE_COUNT)
+ pass_counts = new(GC_QUEUE_COUNT)
+ fail_counts = new(GC_QUEUE_COUNT)
+ for(var/i in 1 to GC_QUEUE_COUNT)
+ queues[i] = list()
+ pass_counts[i] = 0
+ fail_counts[i] = 0
/datum/controller/subsystem/garbage/proc/HandleQueue(level = GC_QUEUE_CHECK)
if (level == GC_QUEUE_CHECK)
@@ -153,7 +165,6 @@ SUBSYSTEM_DEF(garbage)
if(GCd_at_time > cut_off_time)
break // Everything else is newer, skip them
count++
-
var/refID = L[2]
var/datum/D
D = locate(refID)
@@ -162,8 +173,8 @@ SUBSYSTEM_DEF(garbage)
++gcedlasttick
++totalgcs
pass_counts[level]++
- #ifdef LEGACY_REFERENCE_TRACKING
- reference_find_on_fail -= refID //It's deleted we don't care anymore.
+ #ifdef REFERENCE_TRACKING
+ reference_find_on_fail -= refID //It's deleted we don't care anymore.
#endif
if (MC_TICK_CHECK)
return
@@ -171,35 +182,43 @@ SUBSYSTEM_DEF(garbage)
// Something's still referring to the qdel'd object.
fail_counts[level]++
+
+ #ifdef REFERENCE_TRACKING
+ var/ref_searching = FALSE
+ #endif
+
switch (level)
if (GC_QUEUE_CHECK)
#ifdef REFERENCE_TRACKING
- D.find_references()
- #elif defined(LEGACY_REFERENCE_TRACKING)
if(reference_find_on_fail[refID])
- D.find_references_legacy()
+ INVOKE_ASYNC(D, /datum/proc/find_references)
+ ref_searching = TRUE
#ifdef GC_FAILURE_HARD_LOOKUP
else
- D.find_references_legacy()
+ INVOKE_ASYNC(D, /datum/proc/find_references)
+ ref_searching = TRUE
#endif
reference_find_on_fail -= refID
#endif
var/type = D.type
var/datum/qdel_item/I = items[type]
- #ifdef TESTING
+
log_world("## TESTING: GC: -- \ref[D] | [type] was unable to be GC'd --")
+ #ifdef TESTING
for(var/c in GLOB.admins) //Using testing() here would fill the logs with ADMIN_VV garbage
var/client/admin = c
if(!check_rights_for(admin, R_ADMIN))
continue
to_chat(admin, "## TESTING: GC: -- [ADMIN_VV(D)] | [type] was unable to be GC'd --")
- testing("GC: -- \ref[src] | [type] was unable to be GC'd --")
- #endif
- #ifdef REFERENCE_TRACKING
- GLOB.deletion_failures += D //It should no longer be bothered by the GC, manual deletion only.
- continue
#endif
I.failures++
+
+ if (I.qdel_flags & QDEL_ITEM_SUSPENDED_FOR_LAG)
+ #ifdef REFERENCE_TRACKING
+ if(ref_searching)
+ return //ref searching intentionally cancels all further fires while running so things that hold references don't end up getting deleted, so we want to return here instead of continue
+ #endif
+ continue
if (GC_QUEUE_HARDDELETE)
HardDelete(D)
if (MC_TICK_CHECK)
@@ -208,27 +227,17 @@ SUBSYSTEM_DEF(garbage)
Queue(D, level+1)
+ #ifdef REFERENCE_TRACKING
+ if(ref_searching)
+ return
+ #endif
+
if (MC_TICK_CHECK)
return
if (count)
queue.Cut(1,count+1)
count = 0
-#ifdef LEGACY_REFERENCE_TRACKING
-/datum/controller/subsystem/garbage/proc/add_type_to_findref(type)
- if(!ispath(type))
- return "NOT A VAILD PATH"
- reference_find_on_fail_types |= typecacheof(type)
-
-/datum/controller/subsystem/garbage/proc/remove_type_from_findref(type)
- if(!ispath(type))
- return "NOT A VALID PATH"
- reference_find_on_fail_types -= typesof(type)
-
-/datum/controller/subsystem/garbage/proc/clear_findref_types()
- reference_find_on_fail_types = list()
-#endif
-
/datum/controller/subsystem/garbage/proc/Queue(datum/D, level = GC_QUEUE_CHECK)
if (isnull(D))
return
@@ -238,63 +247,66 @@ SUBSYSTEM_DEF(garbage)
var/gctime = world.time
var/refid = "\ref[D]"
-#ifdef LEGACY_REFERENCE_TRACKING
- if(reference_find_on_fail_types[D.type])
- SSgarbage.reference_find_on_fail[REF(D)] = TRUE
-#endif
-
D.gc_destroyed = gctime
var/list/queue = queues[level]
+
queue[++queue.len] = list(gctime, refid) // not += for byond reasons
//this is mainly to separate things profile wise.
/datum/controller/subsystem/garbage/proc/HardDelete(datum/D)
- var/time = world.timeofday
- var/tick = TICK_USAGE
- var/ticktime = world.time
++delslasttick
++totaldels
var/type = D.type
var/refID = "\ref[D]"
+ var/tick_usage = TICK_USAGE
del(D)
-
- tick = (TICK_USAGE-tick+((world.time-ticktime)/world.tick_lag*100))
+ tick_usage = TICK_USAGE_TO_MS(tick_usage)
var/datum/qdel_item/I = items[type]
-
I.hard_deletes++
- I.hard_delete_time += TICK_DELTA_TO_MS(tick)
+ I.hard_delete_time += tick_usage
+ if (tick_usage > I.hard_delete_max)
+ I.hard_delete_max = tick_usage
+ if (tick_usage > highest_del_ms)
+ highest_del_ms = tick_usage
+ highest_del_type_string = "[type]"
+ var/time = MS2DS(tick_usage)
- if (tick > highest_del_tickusage)
- highest_del_tickusage = tick
- time = world.timeofday - time
- if (!time && TICK_DELTA_TO_MS(tick) > 1)
- time = TICK_DELTA_TO_MS(tick)/100
- if (time > highest_del_time)
- highest_del_time = time
- if (time > 10)
- log_game("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete)")
- message_admins("Error: [type]([refID]) took longer than 1 second to delete (took [time/10] seconds to delete).")
+ if (time > 0.1 SECONDS)
postpone(time)
+ var/threshold = CONFIG_GET(number/hard_deletes_overrun_threshold)
+ if (threshold && (time > threshold SECONDS))
+ if (!(I.qdel_flags & QDEL_ITEM_ADMINS_WARNED))
+ log_game("Error: [type]([refID]) took longer than [threshold] seconds to delete (took [round(time/10, 0.1)] seconds to delete)")
+ message_admins("Error: [type]([refID]) took longer than [threshold] seconds to delete (took [round(time/10, 0.1)] seconds to delete).")
+ I.qdel_flags |= QDEL_ITEM_ADMINS_WARNED
+ I.hard_deletes_over_threshold++
+ var/overrun_limit = CONFIG_GET(number/hard_deletes_overrun_limit)
+ if (overrun_limit && I.hard_deletes_over_threshold >= overrun_limit)
+ I.qdel_flags |= QDEL_ITEM_SUSPENDED_FOR_LAG
/datum/controller/subsystem/garbage/Recover()
+ InitQueues() //We first need to create the queues before recovering data
if (istype(SSgarbage.queues))
for (var/i in 1 to SSgarbage.queues.len)
queues[i] |= SSgarbage.queues[i]
-
+/// Qdel Item: Holds statistics on each type that passes thru qdel
/datum/qdel_item
- var/name = ""
- var/qdels = 0 //Total number of times it's passed thru qdel.
- var/destroy_time = 0 //Total amount of milliseconds spent processing this type's Destroy()
- var/failures = 0 //Times it was queued for soft deletion but failed to soft delete.
- var/hard_deletes = 0 //Different from failures because it also includes QDEL_HINT_HARDDEL deletions
- var/hard_delete_time = 0//Total amount of milliseconds spent hard deleting this type.
- var/no_respect_force = 0//Number of times it's not respected force=TRUE
- var/no_hint = 0 //Number of times it's not even bother to give a qdel hint
- var/slept_destroy = 0 //Number of times it's slept in its destroy
+ var/name = "" //!Holds the type as a string for this type
+ var/qdels = 0 //!Total number of times it's passed thru qdel.
+ var/destroy_time = 0 //!Total amount of milliseconds spent processing this type's Destroy()
+ var/failures = 0 //!Times it was queued for soft deletion but failed to soft delete.
+ var/hard_deletes = 0 //!Different from failures because it also includes QDEL_HINT_HARDDEL deletions
+ var/hard_delete_time = 0 //!Total amount of milliseconds spent hard deleting this type.
+ var/hard_delete_max = 0 //!Highest time spent hard_deleting this in ms.
+ var/hard_deletes_over_threshold = 0 //!Number of times hard deletes took longer than the configured threshold
+ var/no_respect_force = 0 //!Number of times it's not respected force=TRUE
+ var/no_hint = 0 //!Number of times it's not even bother to give a qdel hint
+ var/slept_destroy = 0 //!Number of times it's slept in its destroy
+ var/qdel_flags = 0 //!Flags related to this type's trip thru qdel.
/datum/qdel_item/New(mytype)
name = "[mytype]"
@@ -307,12 +319,12 @@ SUBSYSTEM_DEF(garbage)
if(!istype(D))
del(D)
return
+
var/datum/qdel_item/I = SSgarbage.items[D.type]
if (!I)
I = SSgarbage.items[D.type] = new /datum/qdel_item(D.type)
I.qdels++
-
if(isnull(D.gc_destroyed))
if (SEND_SIGNAL(D, COMSIG_PARENT_PREQDELETED, force)) // Give the components a chance to prevent their parent from being deleted
return
@@ -328,12 +340,12 @@ SUBSYSTEM_DEF(garbage)
if(!D)
return
switch(hint)
- if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
+ if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
SSgarbage.Queue(D)
if (QDEL_HINT_IWILLGC)
D.gc_destroyed = world.time
return
- if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
+ if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
if(!force)
D.gc_destroyed = null //clear the gc variable (important!)
return
@@ -350,17 +362,17 @@ SUBSYSTEM_DEF(garbage)
I.no_respect_force++
SSgarbage.Queue(D)
- if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete
+ if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete
SSgarbage.Queue(D, GC_QUEUE_HARDDELETE)
- if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
+ if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
SSgarbage.HardDelete(D)
- #ifdef LEGACY_REFERENCE_TRACKING
- if (QDEL_HINT_FINDREFERENCE) //qdel will, if LEGACY_REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
+ #ifdef REFERENCE_TRACKING
+ if (QDEL_HINT_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.Queue(D)
- D.find_references_legacy()
- if (QDEL_HINT_IFFAIL_FINDREFERENCE)
+ D.find_references()
+ if (QDEL_HINT_IFFAIL_FINDREFERENCE) //qdel will, if REFERENCE_TRACKING is enabled and the object fails to collect, display all references to this object.
SSgarbage.Queue(D)
- SSgarbage.reference_find_on_fail[REF(D)] = TRUE
+ SSgarbage.reference_find_on_fail["\ref[D]"] = TRUE
#endif
else
#ifdef TESTING
@@ -371,18 +383,3 @@ SUBSYSTEM_DEF(garbage)
SSgarbage.Queue(D)
else if(D.gc_destroyed == GC_CURRENTLY_BEING_QDELETED)
CRASH("[D.type] destroy proc was called multiple times, likely due to a qdel loop in the Destroy logic")
-
-#ifdef TESTING
-/proc/writeDatumCount()
- var/list/datums = list()
- for(var/datum/D in world)
- datums[D.type] += 1
- for(var/datum/D)
- datums[D.type] += 1
- datums = sortTim(datums, /proc/cmp_numeric_dsc, associative = TRUE)
- if(fexists("data/DATUMCOUNT.txt"))
- fdel("data/DATUMCOUNT.txt")
- var/outfile = file("data/DATUMCOUNT.txt")
- for(var/path in datums)
- outfile << "[datums[path]]\t\t\t\t\t[path]"
-#endif
diff --git a/config/entries/general.txt b/config/entries/general.txt
index 3584af63c7..b3130565e4 100644
--- a/config/entries/general.txt
+++ b/config/entries/general.txt
@@ -491,3 +491,9 @@ ALLOW_CUSTOM_SKINTONES
## Allows pAI custom holoforms
PAI_CUSTOM_HOLOFORMS
+
+## How long in seconds after which a hard delete is treated as causing lag. This can be a float and supports a precision as low as nanoseconds.
+#HARD_DELETES_OVERRUN_THRESHOLD 0.5
+
+## Once a typepath causes overrun from hard deletes this many times, stop hard deleting it on garbage collection failures. (set to 0 to disable)
+#HARD_DELETES_OVERRUN_LIMIT 0
diff --git a/dependencies.sh b/dependencies.sh
index cdbdcd98df..aca82a3a05 100644
--- a/dependencies.sh
+++ b/dependencies.sh
@@ -8,20 +8,20 @@ export BYOND_MAJOR=514
export BYOND_MINOR=1556
#rust_g git tag
-export RUST_G_VERSION=0.4.8
-
-#auxmos git tag
-export AUXMOS_VERSION=v0.2.3
+export RUST_G_VERSION=0.4.10
#node version
export NODE_VERSION=12
-export NODE_VERSION_PRECISE=12.20.0
+export NODE_VERSION_PRECISE=12.22.4
# SpacemanDMM git tag
-export SPACEMAN_DMM_VERSION=suite-1.6
-
-# Extools git tag
-export EXTOOLS_VERSION=v0.0.7
+export SPACEMAN_DMM_VERSION=suite-1.7
# Python version for mapmerge and other tools
export PYTHON_VERSION=3.6.8
+
+# Auxmos git tag
+export AUXMOS_VERSION=v0.2.3
+
+# Extools git tag
+export EXTOOLS_VERSION=v0.0.7
From 6739e349a054603a6f78e92ecbd1456fd185162c Mon Sep 17 00:00:00 2001
From: LetterN <24603524+LetterN@users.noreply.github.com>
Date: Wed, 8 Sep 2021 09:50:07 +0800
Subject: [PATCH 04/11] heretics LOVES this - Also ian's birthday!
---
code/__DEFINES/rust_g.dm | 15 +-
code/__DEFINES/rust_g_overrides.dm | 3 +
code/__DEFINES/traits.dm | 4 +
.../configuration/entries/admin.dm | 4 +-
code/datums/http.dm | 14 +-
code/modules/admin/topic.dm | 15 +-
code/modules/holiday/holidays.dm | 12 +
.../mapping_helpers/_mapping_helpers.dm | 362 ++++++++++++++++--
.../mapping/mapping_helpers/baseturf.dm | 7 +-
config/entries/admin.txt | 6 +-
rust_g.dll | Bin 8959582 -> 6284800 bytes
tgstation.dme | 1 +
12 files changed, 395 insertions(+), 48 deletions(-)
create mode 100644 code/__DEFINES/rust_g_overrides.dm
diff --git a/code/__DEFINES/rust_g.dm b/code/__DEFINES/rust_g.dm
index 988acd3dae..0da05e7c1d 100644
--- a/code/__DEFINES/rust_g.dm
+++ b/code/__DEFINES/rust_g.dm
@@ -38,6 +38,9 @@
#define RUST_G (__rust_g || __detect_rust_g())
#endif
+/// Gets the version of rust_g
+/proc/rustg_get_version() return call(RUST_G, "get_version")()
+
/**
* This proc generates a cellular automata noise grid which can be used in procedural generation methods.
*
@@ -77,8 +80,8 @@
#define RUSTG_HTTP_METHOD_PATCH "patch"
#define RUSTG_HTTP_METHOD_HEAD "head"
#define RUSTG_HTTP_METHOD_POST "post"
-#define rustg_http_request_blocking(method, url, body, headers) call(RUST_G, "http_request_blocking")(method, url, body, headers)
-#define rustg_http_request_async(method, url, body, headers) call(RUST_G, "http_request_async")(method, url, body, headers)
+#define rustg_http_request_blocking(method, url, body, headers, options) call(RUST_G, "http_request_blocking")(method, url, body, headers, options)
+#define rustg_http_request_async(method, url, body, headers, options) call(RUST_G, "http_request_async")(method, url, body, headers, options)
#define rustg_http_check_request(req_id) call(RUST_G, "http_check_request")(req_id)
#define RUSTG_JOB_NO_RESULTS_YET "NO RESULTS YET"
@@ -99,3 +102,11 @@
#define rustg_sql_disconnect_pool(handle) call(RUST_G, "sql_disconnect_pool")(handle)
#define rustg_sql_check_query(job_id) call(RUST_G, "sql_check_query")("[job_id]")
+#define rustg_url_encode(text) call(RUST_G, "url_encode")(text)
+#define rustg_url_decode(text) call(RUST_G, "url_decode")(text)
+
+#ifdef RUSTG_OVERRIDE_BUILTINS
+ #define url_encode(text) rustg_url_encode(text)
+ #define url_decode(text) rustg_url_decode(text)
+#endif
+
diff --git a/code/__DEFINES/rust_g_overrides.dm b/code/__DEFINES/rust_g_overrides.dm
new file mode 100644
index 0000000000..57de7d96ac
--- /dev/null
+++ b/code/__DEFINES/rust_g_overrides.dm
@@ -0,0 +1,3 @@
+// RUSTG_OVERRIDE_BUILTINS is not used since the file APIs don't work well over Linux.
+#define url_encode(text) rustg_url_encode("[text]")
+#define url_decode(text) rustg_url_decode("[text]")
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index eb9bdccc22..cd94e5790b 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -343,3 +343,7 @@
#define STICKY_NODROP "sticky-nodrop" //sticky nodrop sounds like a bad soundcloud rapper's name
#define TRAIT_SACRIFICED "sacrificed" //Makes sure that people cant be cult sacrificed twice.
#define TRAIT_SPACEWALK "spacewalk"
+
+
+/// obtained from mapping helper
+#define MAPPING_HELPER_TRAIT "mapping-helper"
diff --git a/code/controllers/configuration/entries/admin.dm b/code/controllers/configuration/entries/admin.dm
index 3b5b437742..1f9b5d460f 100644
--- a/code/controllers/configuration/entries/admin.dm
+++ b/code/controllers/configuration/entries/admin.dm
@@ -39,7 +39,9 @@
/datum/config_entry/flag/announce_admin_login
-/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API
+/datum/config_entry/string/centcom_ban_db // URL for the CentCom Galactic Ban DB API
+
+/datum/config_entry/string/centcom_source_whitelist
/datum/config_entry/flag/autoadmin // if autoadmin is enabled
protection = CONFIG_ENTRY_LOCKED
diff --git a/code/datums/http.dm b/code/datums/http.dm
index 2a9b53f131..49b183fde6 100644
--- a/code/datums/http.dm
+++ b/code/datums/http.dm
@@ -6,10 +6,12 @@
var/body
var/headers
var/url
+ /// If present response body will be saved to this file.
+ var/output_file
var/_raw_response
-/datum/http_request/proc/prepare(method, url, body = "", list/headers)
+/datum/http_request/proc/prepare(method, url, body = "", list/headers, output_file)
if (!length(headers))
headers = ""
else
@@ -19,15 +21,16 @@
src.url = url
src.body = body
src.headers = headers
+ src.output_file = output_file
/datum/http_request/proc/execute_blocking()
- _raw_response = rustg_http_request_blocking(method, url, body, headers)
+ _raw_response = rustg_http_request_blocking(method, url, body, headers, build_options())
/datum/http_request/proc/begin_async()
if (in_progress)
CRASH("Attempted to re-use a request object.")
- id = rustg_http_request_async(method, url, body, headers)
+ id = rustg_http_request_async(method, url, body, headers, build_options())
if (isnull(text2num(id)))
stack_trace("Proc error: [id]")
@@ -35,6 +38,11 @@
else
in_progress = TRUE
+/datum/http_request/proc/build_options()
+ if(output_file)
+ return json_encode(list("output_filename"=output_file,"body_filename"=null))
+ return null
+
/datum/http_request/proc/is_complete()
if (isnull(id))
return TRUE
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 953835bff0..4224b406b3 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -2862,7 +2862,7 @@
return
if(!CONFIG_GET(string/centcom_ban_db))
- to_chat(usr, "Centcom Galactic Ban DB is disabled!")
+ to_chat(usr, span_warning("Centcom Galactic Ban DB is disabled!"))
return
var/ckey = href_list["centcomlookup"]
@@ -2889,8 +2889,19 @@
dat += "0 bans detected for [ckey]"
else
bans = json_decode(response["body"])
- dat += "[bans.len] ban\s detected for [ckey]"
+
+ //Ignore bans from non-whitelisted sources, if a whitelist exists
+ var/list/valid_sources
+ if(CONFIG_GET(string/centcom_source_whitelist))
+ valid_sources = splittext(CONFIG_GET(string/centcom_source_whitelist), ",")
+ dat += "Bans detected for [ckey]"
+ else
+ //Ban count is potentially inaccurate if they're using a whitelist
+ dat += "[bans.len] ban\s detected for [ckey]"
+
for(var/list/ban in bans)
+ if(valid_sources && !(ban["sourceName"] in valid_sources))
+ continue
dat += "Server: [sanitize(ban["sourceName"])]
"
dat += "RP Level: [sanitize(ban["sourceRoleplayLevel"])]
"
dat += "Type: [sanitize(ban["type"])]
"
diff --git a/code/modules/holiday/holidays.dm b/code/modules/holiday/holidays.dm
index e3f5264568..239246cd59 100644
--- a/code/modules/holiday/holidays.dm
+++ b/code/modules/holiday/holidays.dm
@@ -641,6 +641,18 @@ Since Ramadan is an entire month that lasts 29.5 days on average, the start and
/datum/holiday/easter/getStationPrefix()
return pick("Fluffy","Bunny","Easter","Egg")
+/datum/holiday/ianbirthday
+ name = "Ian's Birthday" //github.com/tgstation/tgstation/commit/de7e4f0de0d568cd6e1f0d7bcc3fd34700598acb
+ begin_month = SEPTEMBER
+ begin_day = 9
+ end_day = 10
+
+/datum/holiday/ianbirthday/greet()
+ return "Happy birthday, Ian!"
+
+/datum/holiday/ianbirthday/getStationPrefix()
+ return pick("Ian", "Corgi", "Erro")
+
//Random citadel thing for halloween species
/proc/force_enable_halloween_species()
var/list/oldlist = SSevents.holidays
diff --git a/code/modules/mapping/mapping_helpers/_mapping_helpers.dm b/code/modules/mapping/mapping_helpers/_mapping_helpers.dm
index 4de16ba350..a96b81528f 100644
--- a/code/modules/mapping/mapping_helpers/_mapping_helpers.dm
+++ b/code/modules/mapping/mapping_helpers/_mapping_helpers.dm
@@ -8,61 +8,73 @@
..()
return late ? INITIALIZE_HINT_LATELOAD : INITIALIZE_HINT_QDEL
+
//airlock helpers
/obj/effect/mapping_helpers/airlock
layer = DOOR_HELPER_LAYER
+/obj/effect/mapping_helpers/airlock/Initialize(mapload)
+ . = ..()
+ if(!mapload)
+ log_mapping("[src] spawned outside of mapload!")
+ return
+ var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
+ if(!airlock)
+ log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
+ else
+ payload(airlock)
+
+/obj/effect/mapping_helpers/airlock/proc/payload(obj/machinery/door/airlock/payload)
+ return
+
/obj/effect/mapping_helpers/airlock/cyclelink_helper
name = "airlock cyclelink helper"
icon_state = "airlock_cyclelink_helper"
-/obj/effect/mapping_helpers/airlock/cyclelink_helper/Initialize(mapload)
- . = ..()
- if(!mapload)
- log_mapping("[src] spawned outside of mapload!")
- return
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
- if(airlock)
- if(airlock.cyclelinkeddir)
- log_mapping("[src] at [AREACOORD(src)] tried to set [airlock] cyclelinkeddir, but it's already set!")
- else
- airlock.cyclelinkeddir = dir
+/obj/effect/mapping_helpers/airlock/cyclelink_helper/payload(obj/machinery/door/airlock/airlock)
+ if(airlock.cyclelinkeddir)
+ log_mapping("[src] at [AREACOORD(src)] tried to set [airlock] cyclelinkeddir, but it's already set!")
else
- log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
+ airlock.cyclelinkeddir = dir
+/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi
+ name = "airlock multi-cyclelink helper"
+ icon_state = "airlock_multicyclelink_helper"
+ var/cycle_id
+
+/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi/payload(obj/machinery/door/airlock/airlock)
+ if(airlock.closeOtherId)
+ log_mapping("[src] at [AREACOORD(src)] tried to set [airlock] closeOtherId, but it's already set!")
+ else
+ airlock.closeOtherId = cycle_id
/obj/effect/mapping_helpers/airlock/locked
name = "airlock lock helper"
icon_state = "airlock_locked_helper"
-/obj/effect/mapping_helpers/airlock/locked/Initialize(mapload)
- . = ..()
- if(!mapload)
- log_mapping("[src] spawned outside of mapload!")
- return
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
- if(airlock)
- if(airlock.locked)
- log_mapping("[src] at [AREACOORD(src)] tried to bolt [airlock] but it's already locked!")
- else
- airlock.locked = TRUE
+/obj/effect/mapping_helpers/airlock/locked/payload(obj/machinery/door/airlock/airlock)
+ if(airlock.locked)
+ log_mapping("[src] at [AREACOORD(src)] tried to bolt [airlock] but it's already locked!")
else
- log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
+ airlock.locked = TRUE
+
/obj/effect/mapping_helpers/airlock/unres
name = "airlock unresctricted side helper"
icon_state = "airlock_unres_helper"
-/obj/effect/mapping_helpers/airlock/unres/Initialize(mapload)
- . = ..()
- if(!mapload)
- log_mapping("[src] spawned outside of mapload!")
- return
- var/obj/machinery/door/airlock/airlock = locate(/obj/machinery/door/airlock) in loc
- if(airlock)
- airlock.unres_sides ^= dir
+/obj/effect/mapping_helpers/airlock/unres/payload(obj/machinery/door/airlock/airlock)
+ airlock.unres_sides ^= dir
+
+/obj/effect/mapping_helpers/airlock/abandoned
+ name = "airlock abandoned helper"
+ icon_state = "airlock_abandoned"
+
+/obj/effect/mapping_helpers/airlock/abandoned/payload(obj/machinery/door/airlock/airlock)
+ if(airlock.abandoned)
+ log_mapping("[src] at [AREACOORD(src)] tried to make [airlock] abandoned but it's already abandoned!")
else
- log_mapping("[src] failed to find an airlock at [AREACOORD(src)]")
+ airlock.abandoned = TRUE
//needs to do its thing before spawn_rivers() is called
@@ -79,9 +91,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
//This helper applies components to things on the map directly.
/obj/effect/mapping_helpers/component_injector
name = "Component Injector"
+ icon_state = "component"
late = TRUE
- var/target_type
- var/target_name
+ var/all = FALSE //Will inject into all fitting the criteria if true, otherwise first found
+ var/target_type //Will inject into atoms of this type
+ var/target_name //Will inject into atoms with this name
var/component_type
//Late init so everything is likely ready and loaded (no warranty)
@@ -98,8 +112,11 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
continue
var/cargs = build_args()
A._AddComponent(cargs)
+ if(!all)
+ qdel(src)
+ return
+ if(all)
qdel(src)
- return
/obj/effect/mapping_helpers/component_injector/proc/build_args()
return list(component_type)
@@ -115,3 +132,276 @@ INITIALIZE_IMMEDIATE(/obj/effect/mapping_helpers/no_lava)
CRASH("Wrong disease type passed in.")
var/datum/disease/D = new disease_type()
return list(component_type,D)
+
+// /obj/effect/mapping_helpers/component_injector/areabound
+// name = "Areabound Injector"
+// icon_state = "component_areabound"
+// component_type = /datum/component/areabound
+// target_type = /atom/movable
+
+/obj/effect/mapping_helpers/dead_body_placer
+ name = "Dead Body placer"
+ late = TRUE
+ icon_state = "deadbodyplacer"
+ var/bodycount = 2 //number of bodies to spawn
+
+/obj/effect/mapping_helpers/dead_body_placer/LateInitialize()
+ var/area/a = get_area(src)
+ var/list/trays = list()
+ for (var/i in a.contents)
+ if (istype(i, /obj/structure/bodycontainer/morgue))
+ trays += i
+ if(!trays.len)
+ log_mapping("[src] at [x],[y] could not find any morgues.")
+ return
+ for (var/i = 1 to bodycount)
+ var/obj/structure/bodycontainer/morgue/j = pick(trays)
+ var/mob/living/carbon/human/h = new /mob/living/carbon/human(j, 1)
+ h.death()
+ for (var/part in h.internal_organs) //randomly remove organs from each body, set those we keep to be in stasis
+ if (prob(40))
+ qdel(part)
+ else
+ var/obj/item/organ/O = part
+ O.organ_flags |= ORGAN_FROZEN
+ j.update_appearance()
+ qdel(src)
+
+
+//On Ian's birthday, the hop's office is decorated.
+/obj/effect/mapping_helpers/ianbirthday
+ name = "Ian's Bday Helper"
+ late = TRUE
+ icon_state = "iansbdayhelper"
+ var/balloon_clusters = 2
+
+/obj/effect/mapping_helpers/ianbirthday/LateInitialize()
+ if(locate(/datum/holiday/ianbirthday) in SSevents.holidays)
+ birthday()
+ qdel(src)
+
+/obj/effect/mapping_helpers/ianbirthday/proc/birthday()
+ var/area/a = get_area(src)
+ var/list/table = list()//should only be one aka the front desk, but just in case...
+ var/list/openturfs = list()
+
+ //confetti and a corgi balloon! (and some list stuff for more decorations)
+ for(var/thing in a.contents)
+ if(istype(thing, /obj/structure/table/reinforced))
+ table += thing
+ if(isopenturf(thing))
+ // new /obj/effect/decal/cleanable/confetti(thing)
+ // if(locate(/obj/structure/bed/dogbed/ian) in thing)
+ // new /obj/item/toy/balloon/corgi(thing)
+ // else
+ openturfs += thing
+
+ //cake + knife to cut it!
+ if(length(table))
+ var/turf/food_turf = get_turf(pick(table))
+ new /obj/item/kitchen/knife(food_turf)
+ var/obj/item/reagent_containers/food/snacks/store/cake/birthday/iancake = new(food_turf)
+ iancake.desc = "Happy birthday, Ian!"
+ // remind me to give ian proper baloons!
+ //some balloons! this picks an open turf and pops a few balloons in and around that turf, yay.
+ // for(var/i in 1 to balloon_clusters)
+ // var/turf/clusterspot = pick_n_take(openturfs)
+ // new /obj/item/toy/balloon(clusterspot)
+ // var/balloons_left_to_give = 3 //the amount of balloons around the cluster
+ // var/list/dirs_to_balloon = GLOB.cardinals.Copy()
+ // while(balloons_left_to_give > 0)
+ // balloons_left_to_give--
+ // var/chosen_dir = pick_n_take(dirs_to_balloon)
+ // var/turf/balloonstep = get_step(clusterspot, chosen_dir)
+ // var/placed = FALSE
+ // if(isopenturf(balloonstep))
+ // var/obj/item/toy/balloon/B = new(balloonstep)//this clumps the cluster together
+ // placed = TRUE
+ // if(chosen_dir == NORTH)
+ // B.pixel_y -= 10
+ // if(chosen_dir == SOUTH)
+ // B.pixel_y += 10
+ // if(chosen_dir == EAST)
+ // B.pixel_x -= 10
+ // if(chosen_dir == WEST)
+ // B.pixel_x += 10
+ // if(!placed)
+ // new /obj/item/toy/balloon(clusterspot)
+ //remind me to add wall decor!
+
+/obj/effect/mapping_helpers/ianbirthday/admin//so admins may birthday any room
+ name = "generic birthday setup"
+ icon_state = "bdayhelper"
+
+/obj/effect/mapping_helpers/ianbirthday/admin/LateInitialize()
+ birthday()
+ qdel(src)
+
+//Ian, like most dogs, loves a good new years eve party.
+/obj/effect/mapping_helpers/iannewyear
+ name = "Ian's New Years Helper"
+ late = TRUE
+ icon_state = "iansnewyrshelper"
+
+/obj/effect/mapping_helpers/iannewyear/LateInitialize()
+ if(SSevents.holidays && SSevents.holidays[NEW_YEAR])
+ fireworks()
+ qdel(src)
+
+/obj/effect/mapping_helpers/iannewyear/proc/fireworks()
+ var/area/a = get_area(src)
+ var/list/table = list()//should only be one aka the front desk, but just in case...
+ var/list/openturfs = list()
+
+ for(var/thing in a.contents)
+ if(istype(thing, /obj/structure/table/reinforced))
+ table += thing
+ else if(isopenturf(thing))
+ if(locate(/obj/structure/bed/dogbed/ian) in thing)
+ new /obj/item/clothing/head/festive(thing)
+ var/obj/item/reagent_containers/food/drinks/bottle/champagne/iandrink = new(thing)
+ iandrink.name = "dog champagne"
+ iandrink.pixel_y += 8
+ iandrink.pixel_x += 8
+ else
+ openturfs += thing
+
+ var/turf/fireworks_turf = get_turf(pick(table))
+ var/obj/item/storage/box/matches/matchbox = new(fireworks_turf)
+ matchbox.pixel_y += 8
+ matchbox.pixel_x -= 3
+ // new /obj/item/storage/box/fireworks/dangerous(fireworks_turf) //dangerous version for extra holiday memes.
+
+//lets mappers place notes on airlocks with custom info or a pre-made note from a path
+/obj/effect/mapping_helpers/airlock_note_placer
+ name = "Airlock Note Placer"
+ late = TRUE
+ icon_state = "airlocknoteplacer"
+ var/note_info //for writing out custom notes without creating an extra paper subtype
+ var/note_name //custom note name
+ var/note_path //if you already have something wrote up in a paper subtype, put the path here
+
+/obj/effect/mapping_helpers/airlock_note_placer/LateInitialize()
+ var/turf/turf = get_turf(src)
+ if(note_path && !istype(note_path, /obj/item/paper)) //don't put non-paper in the paper slot thank you
+ log_mapping("[src] at [x],[y] had an improper note_path path, could not place paper note.")
+ qdel(src)
+ if(locate(/obj/machinery/door/airlock) in turf)
+ var/obj/machinery/door/airlock/found_airlock = locate(/obj/machinery/door/airlock) in turf
+ if(note_path)
+ found_airlock.note = note_path
+ found_airlock.update_appearance()
+ qdel(src)
+ if(note_info)
+ var/obj/item/paper/paper = new /obj/item/paper(src)
+ if(note_name)
+ paper.name = note_name
+ paper.info = "[note_info]"
+ found_airlock.note = paper
+ paper.forceMove(found_airlock)
+ found_airlock.update_appearance()
+ qdel(src)
+ log_mapping("[src] at [x],[y] had no note_path or note_info, cannot place paper note.")
+ qdel(src)
+ log_mapping("[src] at [x],[y] could not find an airlock on current turf, cannot place paper note.")
+ qdel(src)
+
+//This helper applies traits to things on the map directly.
+/obj/effect/mapping_helpers/trait_injector
+ name = "Trait Injector"
+ icon_state = "trait"
+ late = TRUE
+ ///Will inject into all fitting the criteria if false, otherwise first found.
+ var/first_match_only = TRUE
+ ///Will inject into atoms of this type.
+ var/target_type
+ ///Will inject into atoms with this name.
+ var/target_name
+ ///Name of the trait, in the lower-case text (NOT the upper-case define) form.
+ var/trait_name
+
+//Late init so everything is likely ready and loaded (no warranty)
+/obj/effect/mapping_helpers/trait_injector/LateInitialize()
+ if(!GLOB.trait_name_map)
+ GLOB.trait_name_map = generate_trait_name_map()
+ if(!GLOB.trait_name_map.Find(trait_name))
+ CRASH("Wrong trait in [type] - [trait_name] is not a trait")
+ var/turf/target_turf = get_turf(src)
+ var/matches_found = 0
+ for(var/a in target_turf.GetAllContents())
+ var/atom/atom_on_turf = a
+ if(atom_on_turf == src)
+ continue
+ if(target_name && atom_on_turf.name != target_name)
+ continue
+ if(target_type && !istype(atom_on_turf,target_type))
+ continue
+ ADD_TRAIT(atom_on_turf, trait_name, MAPPING_HELPER_TRAIT)
+ matches_found++
+ if(first_match_only)
+ qdel(src)
+ return
+ if(!matches_found)
+ stack_trace("Trait mapper found no targets at ([x], [y], [z]). First Match Only: [first_match_only ? "true" : "false"] target type: [target_type] | target name: [target_name] | trait name: [trait_name]")
+ qdel(src)
+
+/// Fetches an external dmi and applies to the target object
+/obj/effect/mapping_helpers/custom_icon
+ name = "Custom Icon Helper"
+ icon_state = "trait"
+ late = TRUE
+ ///Will inject into all fitting the criteria if false, otherwise first found.
+ var/first_match_only = TRUE
+ ///Will inject into atoms of this type.
+ var/target_type
+ ///Will inject into atoms with this name.
+ var/target_name
+ /// This is the var tha will be set with the fetched icon. In case you want to set some secondary icon sheets like inhands and such.
+ var/target_variable = "icon"
+ /// This should return raw dmi in response to http get request. For example: "https://github.com/tgstation/SS13-sprites/raw/master/mob/medu.dmi?raw=true"
+ var/icon_url
+
+/obj/effect/mapping_helpers/custom_icon/LateInitialize()
+ ///TODO put this injector stuff under common root
+ var/I = fetch_icon(icon_url)
+ var/turf/target_turf = get_turf(src)
+ var/matches_found = 0
+ for(var/a in target_turf.GetAllContents())
+ var/atom/atom_on_turf = a
+ if(atom_on_turf == src)
+ continue
+ if(target_name && atom_on_turf.name != target_name)
+ continue
+ if(target_type && !istype(atom_on_turf,target_type))
+ continue
+ atom_on_turf.vars[target_variable] = I
+ matches_found++
+ if(first_match_only)
+ qdel(src)
+ return
+ if(!matches_found)
+ stack_trace("[src] found no targets at ([x], [y], [z]). First Match Only: [first_match_only ? "true" : "false"] target type: [target_type] | target name: [target_name]")
+ qdel(src)
+
+/obj/effect/mapping_helpers/custom_icon/proc/fetch_icon(url)
+ var/static/icon_cache = list()
+ var/static/query_in_progress = FALSE //We're using a single tmp file so keep it linear.
+ if(query_in_progress)
+ UNTIL(!query_in_progress)
+ if(icon_cache[url])
+ return icon_cache[url]
+ log_asset("Custom Icon Helper fetching dmi from: [url]")
+ var/datum/http_request/request = new()
+ var/file_name = "tmp/custom_map_icon.dmi"
+ request.prepare(RUSTG_HTTP_METHOD_GET, url , "", "", file_name)
+ query_in_progress = TRUE
+ request.begin_async()
+ UNTIL(request.is_complete())
+ var/datum/http_response/response = request.into_response()
+ if(response.errored || response.status_code != 200)
+ query_in_progress = FALSE
+ CRASH("Failed to fetch mapped custom icon from url [url], code: [response.status_code], error: [response.error]")
+ var/icon/I = new(file_name)
+ icon_cache[url] = I
+ query_in_progress = FALSE
+ return I
diff --git a/code/modules/mapping/mapping_helpers/baseturf.dm b/code/modules/mapping/mapping_helpers/baseturf.dm
index f4bd0d7c7f..4d79d3dba5 100644
--- a/code/modules/mapping/mapping_helpers/baseturf.dm
+++ b/code/modules/mapping/mapping_helpers/baseturf.dm
@@ -30,8 +30,8 @@
qdel(src)
/obj/effect/baseturf_helper/proc/replace_baseturf(turf/thing)
- var/list/baseturf_cache = thing.baseturfs
- if(length(baseturf_cache))
+ if(length(thing.baseturfs))
+ var/list/baseturf_cache = thing.baseturfs.Copy()
for(var/i in baseturf_cache)
if(baseturf_to_replace[i])
baseturf_cache -= i
@@ -44,6 +44,8 @@
else
thing.PlaceOnBottom(null, baseturf)
+
+
/obj/effect/baseturf_helper/space
name = "space baseturf editor"
baseturf = /turf/open/space
@@ -79,4 +81,3 @@
/obj/effect/baseturf_helper/lava_land/surface
name = "lavaland baseturf editor"
baseturf = /turf/open/lava/smooth/lava_land_surface
-
diff --git a/config/entries/admin.txt b/config/entries/admin.txt
index 883bda9422..e583790b82 100644
--- a/config/entries/admin.txt
+++ b/config/entries/admin.txt
@@ -52,8 +52,12 @@ ANNOUNCE_ADMIN_LOGOUT
## Uncomment to have an admin message sent anytime an admin connects to a round in play, you can edit the messages in admin.dm
#ANNOUNCE_ADMIN_LOGIN
+## Uncomment to enable global ban DB using the provided URL. The API should expect to receive a ckey at the end of the URL.
## More API details can be found here: https://centcom.melonmesa.com
-CENTCOM_BAN_DB https://centcom.melonmesa.com/ban/search
+#CENTCOM_BAN_DB https://centcom.melonmesa.com/ban/search
+## Uncomment to enable source whitelisting, a comma-separated list (no spaces) of CentCom sources (sourceName).
+## If enabled, only bans from these servers will be shown to admins using CentCom. The default sources list is an example.
+#CENTCOM_SOURCE_WHITELIST Beestation MRP,TGMC,FTL13
## AUTOADMIN
## The default admin rank
diff --git a/rust_g.dll b/rust_g.dll
index 8ef1c59a105b002a8c2d597eb42e98a846db5825..26f6942861d120395883c04d8c458a2b0d58f402 100644
GIT binary patch
literal 6284800
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%0AqGw(Ohpl-|4bX
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
z
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