docs: private PollingResult _poll(TaskListener listener, SCM scm) throws IOException, InterruptedException {
          if (scm.requiresWorkspaceForPolling()) {
              R b = getSomeBuildWithExistingWorkspace();
              if (b == null) b = getLastBuild();
              // lock the workspace for the given build
              FilePath ws=b.getWorkspace();
  
              WorkspaceOfflineReason workspaceOfflineReason = workspaceOffline( b );
              if ( workspaceOfflineReason != null ) {
                  // workspace offline
                  for (WorkspaceBrowser browser : ExtensionList.lookup(WorkspaceBrowser.class)) {
                      ws = browser.getWorkspace(this);
                      if (ws != null) {
                          return pollWithWorkspace(listener, scm, b, ws, browser.getWorkspaceList());
                      }
                  }
  
                  // At this point we start thinking about triggering a build just to get a workspace,
                  // because otherwise there's no way we can detect changes.
                  // However, first there are some conditions in which we do not want to do so.
                  // give time for agents to come online if we are right after reconnection (JENKINS-8408)
                  long running = Jenkins.getInstance().getInjector().getInstance(Uptime.class).getUptime();
                  long remaining = TimeUnit.MINUTES.toMillis(10)-running;
                  if (remaining>0 && /* this logic breaks tests of polling */!Functions.getIsUnitTest()) {
                      listener.getLogger().print(Messages.AbstractProject_AwaitingWorkspaceToComeOnline(remaining/1000));
                      listener.getLogger().println( " (" + workspaceOfflineReason.name() + ")");
                      return NO_CHANGES;
                  }
  
                  // Do not trigger build, if no suitable agent is online
                  if (workspaceOfflineReason.equals(WorkspaceOfflineReason.all_suitable_nodes_are_offline)) {
                      // No suitable executor is online
                      listener.getLogger().print(Messages.AbstractProject_AwaitingWorkspaceToComeOnline(running/1000));
                      listener.getLogger().println( " (" + workspaceOfflineReason.name() + ")");
                      return NO_CHANGES;
                  }
  
                  Label label = getAssignedLabel();
                  if (label != null && label.isSelfLabel()) {
                      // if the build is fixed on a node, then attempting a build will do us
                      // no good. We should just wait for the agent to come back.
                      listener.getLogger().print(Messages.AbstractProject_NoWorkspace());
                      listener.getLogger().println( " (" + workspaceOfflineReason.name() + ")");
                      return NO_CHANGES;
                  }
  
                  listener.getLogger().println( ws==null
                      ? Messages.AbstractProject_WorkspaceOffline()
                      : Messages.AbstractProject_NoWorkspace());
                  if (isInQueue()) {
                      listener.getLogger().println(Messages.AbstractProject_AwaitingBuildForWorkspace());
                      return NO_CHANGES;
                  }
  
                  // build now, or nothing will ever be built
                  listener.getLogger().print(Messages.AbstractProject_NewBuildForWorkspace());
                  listener.getLogger().println( " (" + workspaceOfflineReason.name() + ")");
                  return BUILD_NOW;
              } else {
                  WorkspaceList l = b.getBuiltOn().toComputer().getWorkspaceList();
                  return pollWithWorkspace(listener, scm, b, ws, l);
              }
  
          } else {
              // polling without workspace
              LOGGER.fine("Polling SCM changes of " + getName());
              if (pollingBaseline==null) // see NOTE-NO-BASELINE above
                  calcPollingBaseline(getLastBuild(),null,listener);
              PollingResult r = scm.poll(this, null, null, listener, pollingBaseline);
              pollingBaseline = r.remote;
              return r;
          }
      }