code: @Override
      public P decorate(P project) {
          if (!isProject(project)) {
              return project;
          }
  
          if (!(getOwner() instanceof TemplateDrivenMultiBranchProject)) {
              throw new IllegalStateException(String.format("%s can only be used with %s.",
                      TemplateDrivenBranchProjectFactory.class.getSimpleName(),
                      TemplateDrivenMultiBranchProject.class.getSimpleName()));
          }
  
          TemplateDrivenMultiBranchProject<P, B> owner = (TemplateDrivenMultiBranchProject<P, B>) getOwner();
  
          Branch branch = getBranch(project);
          String displayName = project.getDisplayNameOrNull();
          boolean wasDisabled = project.isDisabled();
  
          BulkChange bc = new BulkChange(project);
          try {
              updateByXml(project, new StreamSource(owner.getTemplate().getConfigFile().readRaw()));
  
              // Restore settings managed by this plugin
              setBranch(project, branch);
              project.setDisplayName(displayName);
              project.setScm(branch.getScm());
  
              // Workarounds for JENKINS-21017
              project.setBuildDiscarder(owner.getTemplate().getBuildDiscarder());
              project.setCustomWorkspace(owner.getTemplate().getCustomWorkspace());
  
              if (!wasDisabled) {
                  project.enable();
              }
  
              project = super.decorate(project);
  
              bc.commit();
          } catch (IOException e) {
              LOGGER.log(Level.WARNING, "Unable to update project " + project.getName(), e);
          } finally {
              bc.abort();
          }
  
          return project;
      }
docs: Decorates projects by using {@link #updateByXml(AbstractProject, Source)} and saving the configuration,
  rather than only updating the project in memory.
  
  @param project the project to decorate
  @return the project that was just decorated