<commit_before>import {
  ADD_ITEM,
  REMOVE_ITEM,
  SET
} from '../../../../../../src/js/constants/TransactionTypes';
import Networking from '../../../../../../src/js/constants/Networking';

const defaultFieldValues = {
  containerPort: null,
  name: null,
  hostPort: null,
  automaticPort: true,
  protocol: 'tcp',
  portMapping: false,
  loadBalanced: false
};

function reducer(state = [], {type, path = [], value}) {
  if (path == null) {
    return state;
  }

  let joinedPath = path.join('.');

  if (path.includes('portDefinitions')) {
    if (joinedPath === 'portDefinitions') {
      switch (type) {
        case ADD_ITEM:
          let portDefinition = Object.assign({}, defaultFieldValues);
          this.portDefinitions.push(portDefinition);
          break;
        case REMOVE_ITEM:
          this.portDefinitions.splice(value, 1);
          break;
      }
    }

    let index = path[1];
    if (index != null && type === SET) {
      Object.keys(defaultFieldValues).forEach((fieldKey) => {
        if (joinedPath === `portDefinitions.${index}.${fieldKey}`) {
          this.portDefinitions[index][fieldKey] = value;
        }
      });

      // If port is assigned automatically, remove hostPort
      if (this.portDefinitions[index].automaticPort) {
        this.portDefinitions[index].hostPort = null;
      }
    }
  }

  return this.portDefinitions;
};

module.exports = {
  JSONReducer(state = [], action) {
    if (!this.portDefinitions) {
      this.portDefinitions = [];
    }

    let {path = [], value} = action;
    if (!this.appState) {
      this.appState = {
        id: '',
        hasContainer: false,
        networkType: Networking.type.HOST
      };
    }

    let joinedPath = path.join('.');
    if (joinedPath === 'networking.type') {
      this.appState.networkType = value;
    }

    if (joinedPath === 'container.docker.image' && !!value) {
      this.appState.hasContainer = true;
    }

    if (joinedPath === 'id' && !!value) {
      this.appState.id = value;
    }

    let newState = Object.assign([], reducer.call(this, state, action));

    return newState.map((portDefinition, index) => {
      if (this.appState.networkType === Networking.type.HOST) {
        let port = Number(this.portDefinitions[index].hostPort) || 0;
        let newPortDefinition = {
          name: portDefinition.name,
          port,
          protocol: portDefinition.protocol
        };

        if (this.portDefinitions[index].loadBalanced) {
          newPortDefinition.labels = {
            [`VIP_${index}`]: `${this.appState.id}:${port}`
          };
        }

        return newPortDefinition;
      }
    });
  },

  JSONParser(state) {
    if (state.portDefinitions == null) {
      return [];
    }

    return state;
  },

  FormReducer(state = [], action) {
    if (!this.portDefinitions) {
      this.portDefinitions = [];
    }

    return reducer.call(this, state, action);
  }
};
<commit_msg>Make reducer not modify state<commit_after>import {
  ADD_ITEM,
  REMOVE_ITEM,
  SET
} from '../../../../../../src/js/constants/TransactionTypes';
import Networking from '../../../../../../src/js/constants/Networking';

const defaultFieldValues = {
  containerPort: null,
  name: null,
  hostPort: null,
  automaticPort: true,
  protocol: 'tcp',
  portMapping: false,
  loadBalanced: false
};

function reducer(portDefinitions = [], state = [], {type, path = [], value}) {
  if (path == null) {
    return state;
  }

  let joinedPath = path.join('.');

  if (path.includes('portDefinitions')) {
    if (joinedPath === 'portDefinitions') {
      switch (type) {
        case ADD_ITEM:
          let portDefinition = Object.assign({}, defaultFieldValues);
          portDefinitions.push(portDefinition);
          break;
        case REMOVE_ITEM:
          portDefinitions.splice(value, 1);
          break;
      }
    }

    let index = path[1];
    if (index != null && type === SET) {
      Object.keys(defaultFieldValues).forEach((fieldKey) => {
        if (joinedPath === `portDefinitions.${index}.${fieldKey}`) {
          portDefinitions[index][fieldKey] = value;
        }
      });

      // If port is assigned automatically, remove hostPort
      if (portDefinitions[index].automaticPort) {
        portDefinitions[index].hostPort = null;
      }
    }
  }

  return portDefinitions || [];
};

module.exports = {
  JSONReducer(state = [], action) {
    let {path = [], value} = action;
    if (!this.appState) {
      this.appState = {
        id: '',
        hasContainer: false,
        networkType: Networking.type.HOST
      };
    }

    let joinedPath = path.join('.');
    if (joinedPath === 'networking.type') {
      this.appState.networkType = value;
    }

    if (joinedPath === 'container.docker.image' && !!value) {
      this.appState.hasContainer = true;
    }

    if (joinedPath === 'id' && !!value) {
      this.appState.id = value;
    }

    this.portDefinitions = reducer(this.portDefinitions, state, action);

    return this.portDefinitions.map((portDefinition, index) => {
      if (this.appState.networkType === Networking.type.HOST) {
        let port = Number(this.portDefinitions[index].hostPort) || 0;
        let newPortDefinition = {
          name: portDefinition.name,
          port,
          protocol: portDefinition.protocol
        };

        if (this.portDefinitions[index].loadBalanced) {
          newPortDefinition.labels = {
            [`VIP_${index}`]: `${this.appState.id}:${port}`
          };
        }

        return newPortDefinition;
      }
    });
  },

  JSONParser(state) {
    if (state.portDefinitions == null) {
      return [];
    }

    return state;
  },

  FormReducer(state = [], action) {
    this.portDefinitions = reducer(this.portDefinitions, state, action);

    return this.portDefinitions;
  }
};

{'fraction_non_alphanumeric': 0.15490297097715955, 'fraction_numerical': 0.0010303967027305513, 'mean_word_length': 2.36064627813041, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5759760', 'n_tokens_mistral': 1799, 'n_tokens_neox': 1738, 'n_words': 339}